wip improvements, fixes, change a ton of hud stuff

This commit is contained in:
Bixilon 2021-10-15 21:10:35 +02:00
parent 9c87010abd
commit bcf606de48
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
27 changed files with 289 additions and 187 deletions

View File

@ -16,7 +16,9 @@ package de.bixilon.minosoft.data.player.tab
import de.bixilon.minosoft.data.abilities.Gamemodes import de.bixilon.minosoft.data.abilities.Gamemodes
import de.bixilon.minosoft.data.player.PlayerProperty import de.bixilon.minosoft.data.player.PlayerProperty
import de.bixilon.minosoft.data.scoreboard.Team import de.bixilon.minosoft.data.scoreboard.Team
import de.bixilon.minosoft.data.text.BaseComponent
import de.bixilon.minosoft.data.text.ChatComponent import de.bixilon.minosoft.data.text.ChatComponent
import de.bixilon.minosoft.data.text.RGBColor
import de.bixilon.minosoft.util.KUtil.nullCompare import de.bixilon.minosoft.util.KUtil.nullCompare
data class TabListItem( data class TabListItem(
@ -27,6 +29,24 @@ data class TabListItem(
var properties: Map<String, PlayerProperty> = mutableMapOf(), var properties: Map<String, PlayerProperty> = mutableMapOf(),
var team: Team? = null, var team: Team? = null,
) : Comparable<TabListItem> { ) : Comparable<TabListItem> {
val tabDisplayName: ChatComponent
get() {
val displayName = BaseComponent()
team?.prefix?.let {
displayName += it
}
displayName += displayName.apply {
// ToDo: Set correct formatting code
val color = team?.formattingCode
if (color is RGBColor) {
applyDefaultColor(color)
}
}
team?.suffix?.let {
displayName += it
}
return displayName
}
fun merge(data: TabListItemData) { fun merge(data: TabListItemData) {
specialMerge(data) specialMerge(data)

View File

@ -248,4 +248,14 @@ class BaseComponent : ChatComponent {
this.remove(value) this.remove(value)
} }
} }
override fun equals(other: Any?): Boolean {
if (other === this) {
return true
}
if (other !is BaseComponent) {
return false
}
return parts == other.parts
}
} }

View File

@ -211,6 +211,17 @@ open class TextComponent(
) )
} }
override fun equals(other: Any?): Boolean {
if (other === this) {
return true
}
if (other !is TextComponent) {
return false
}
return message == other.message && color == other.color && formatting == other.formatting && clickEvent == other.clickEvent && hoverEvent == other.hoverEvent
}
companion object { companion object {
val DEFAULT_FORMATTING: Set<ChatFormattingCode> = setOf(PreChatFormattingCodes.SHADOWED) val DEFAULT_FORMATTING: Set<ChatFormattingCode> = setOf(PreChatFormattingCodes.SHADOWED)
} }

View File

@ -38,6 +38,16 @@ class ClickEvent {
this.value = value this.value = value
} }
override fun equals(other: Any?): Boolean {
if (other === this) {
return true
}
if (other !is ClickEvent) {
return false
}
return action == other.action && value == other.value
}
enum class ClickEventActions { enum class ClickEventActions {
OPEN_URL, OPEN_URL,
RUN_COMMAND, RUN_COMMAND,

View File

@ -41,6 +41,17 @@ class HoverEvent {
this.value = value this.value = value
} }
override fun equals(other: Any?): Boolean {
if (other === this) {
return true
}
if (other !is HoverEvent) {
return false
}
return action == other.action && value == other.value
}
enum class HoverEventActions { enum class HoverEventActions {
SHOW_TEXT, SHOW_TEXT,
SHOW_ITEM, SHOW_ITEM,

View File

@ -18,6 +18,7 @@ import de.bixilon.minosoft.gui.rendering.gui.hud.HUDRenderer
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIMeshCache import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIMeshCache
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
import de.bixilon.minosoft.gui.rendering.util.vec.Vec2Util.EMPTY import de.bixilon.minosoft.gui.rendering.util.vec.Vec2Util.EMPTY
import de.bixilon.minosoft.gui.rendering.util.vec.Vec2Util.isSmaller
import de.bixilon.minosoft.gui.rendering.util.vec.Vec2Util.max import de.bixilon.minosoft.gui.rendering.util.vec.Vec2Util.max
import de.bixilon.minosoft.gui.rendering.util.vec.Vec2Util.min import de.bixilon.minosoft.gui.rendering.util.vec.Vec2Util.min
import de.bixilon.minosoft.gui.rendering.util.vec.Vec4Util.EMPTY import de.bixilon.minosoft.gui.rendering.util.vec.Vec4Util.EMPTY
@ -27,28 +28,38 @@ import glm_.vec4.Vec4i
abstract class Element(val hudRenderer: HUDRenderer) { abstract class Element(val hudRenderer: HUDRenderer) {
val renderWindow = hudRenderer.renderWindow val renderWindow = hudRenderer.renderWindow
open var parent: Element? = null
protected open var _parent: Element? = null
open var parent: Element?
get() = _parent
set(value) { set(value) {
field = value _parent = value
checkSilentApply() silentApply()
} }
protected var cache = GUIMeshCache(hudRenderer.matrix, 0) protected var cache = GUIMeshCache(hudRenderer.matrix, 0)
open var cacheEnabled: Boolean = true open var cacheEnabled: Boolean = true
open var initialCacheSize: Int = 100 open var initialCacheSize: Int = 100
open var cacheUpToDate: Boolean = false open var cacheUpToDate: Boolean = false
private var previousMaxSize = Vec2i.EMPTY
protected open var _prefSize: Vec2i = Vec2i.EMPTY
/** /**
* If maxSize was infinity, what size would the element have? * If maxSize was infinity, what size would the element have?
*/ */
open var prefSize: Vec2i = Vec2i.EMPTY open var prefSize: Vec2i
get() = _prefSize
set(value) { set(value) {
field = value _prefSize = value
apply() apply()
} }
open var prefMaxSize: Vec2i = Vec2i(-1, -1) protected open var _prefMaxSize: Vec2i = Vec2i(-1, -1)
open var prefMaxSize: Vec2i
get() = _prefMaxSize
set(value) { set(value) {
field = value _prefMaxSize = value
apply() apply()
} }
@ -71,10 +82,17 @@ abstract class Element(val hudRenderer: HUDRenderer) {
return Vec2i.EMPTY.max(maxSize - margin.spaceSize) return Vec2i.EMPTY.max(maxSize - margin.spaceSize)
} }
open var size: Vec2i = Vec2i.EMPTY protected open var _size: Vec2i = Vec2i.EMPTY
open var size: Vec2i
get() { get() {
return field.min(maxSize) return _size.min(maxSize)
} }
set(value) {
_size = value
apply()
}
protected open var _margin: Vec4i = Vec4i.EMPTY
/** /**
* Margin for the element * Margin for the element
@ -82,9 +100,10 @@ abstract class Element(val hudRenderer: HUDRenderer) {
* The max size already includes the margin, the size not. To get the actual size of an element, add the margin to the element. * The max size already includes the margin, the size not. To get the actual size of an element, add the margin to the element.
* For rendering: Every element adds its padding itself * For rendering: Every element adds its padding itself
*/ */
open var margin: Vec4i = Vec4i.EMPTY open var margin: Vec4i
get() = _margin
set(value) { set(value) {
field = value _margin = value
apply() apply()
} }
@ -119,25 +138,47 @@ abstract class Element(val hudRenderer: HUDRenderer) {
abstract fun forceRender(offset: Vec2i, z: Int, consumer: GUIVertexConsumer): Int abstract fun forceRender(offset: Vec2i, z: Int, consumer: GUIVertexConsumer): Int
/** /**
* Applied all changes made to any property, but does not notify the parent about the change * Force applies all changes made to any property, but does not notify the parent about the change
*
*/ */
abstract fun silentApply() @Deprecated("Generally a bad idea to call")
abstract fun forceSilentApply()
/**
* Force applied all changes made to any property and calls `parent?.onChildChange(this)`
*/
@Deprecated("Generally a bad idea to call")
open fun forceApply() {
forceSilentApply()
parent?.onChildChange(this)
}
/** /**
* Applied all changes made to any property and calls `parent?.onChildChange(this)` * Applied all changes made to any property and calls `parent?.onChildChange(this)`
*/ */
open fun apply() { open fun apply() {
checkSilentApply() if (!silentApply()) {
return
}
parent?.onChildChange(this) parent?.onChildChange(this)
} }
/** /**
* Calls when the client needs to check if it needs to re-prepare (maybe the parent changed?) * Calls when the client needs to check if it needs to apply (maybe the parent changed?) changes
* Otherwise, silentApplies. * Otherwise, force silent applies.
* Can be used to improve the performance * Can be used to improve the performance
*
* @return if applied
*/ */
open fun checkSilentApply() { @Suppress("DEPRECATION")
silentApply() open fun silentApply(): Boolean {
val maxSize = maxSize
if (previousMaxSize != maxSize && (maxSize isSmaller size || maxSize isSmaller prefMaxSize)) {
forceSilentApply()
previousMaxSize = maxSize
return true
}
return true
} }
/** /**

View File

@ -35,7 +35,8 @@ class InfiniteSizeElement(hudRenderer: HUDRenderer) : Element(hudRenderer) {
error("Can not render InfiniteSizeElement") error("Can not render InfiniteSizeElement")
} }
override fun silentApply() = Unit override fun forceSilentApply() = Unit
override fun silentApply(): Boolean = false
override fun apply() = Unit override fun apply() = Unit
} }

View File

@ -18,7 +18,6 @@ import de.bixilon.minosoft.gui.rendering.gui.elements.HorizontalAlignments
import de.bixilon.minosoft.gui.rendering.gui.elements.HorizontalAlignments.Companion.getOffset import de.bixilon.minosoft.gui.rendering.gui.elements.HorizontalAlignments.Companion.getOffset
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.mesh.GUIVertexConsumer import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
import de.bixilon.minosoft.gui.rendering.util.vec.Vec2Util.EMPTY
import de.bixilon.minosoft.gui.rendering.util.vec.Vec4Util.bottom import de.bixilon.minosoft.gui.rendering.util.vec.Vec4Util.bottom
import de.bixilon.minosoft.gui.rendering.util.vec.Vec4Util.horizontal import de.bixilon.minosoft.gui.rendering.util.vec.Vec4Util.horizontal
import de.bixilon.minosoft.gui.rendering.util.vec.Vec4Util.left import de.bixilon.minosoft.gui.rendering.util.vec.Vec4Util.left
@ -39,7 +38,6 @@ open class RowLayout(
override var childAlignment: HorizontalAlignments = HorizontalAlignments.LEFT, override var childAlignment: HorizontalAlignments = HorizontalAlignments.LEFT,
spacing: Int = 0, spacing: Int = 0,
) : Element(hudRenderer), ChildAlignable { ) : Element(hudRenderer), ChildAlignable {
private var _prefSize = Vec2i.EMPTY
private val children: MutableList<Element> = synchronizedListOf() private val children: MutableList<Element> = synchronizedListOf()
override var cacheEnabled: Boolean = false // ToDo: Cache override var cacheEnabled: Boolean = false // ToDo: Cache
@ -51,11 +49,18 @@ open class RowLayout(
var spacing: Int = spacing var spacing: Int = spacing
set(value) { set(value) {
field = value field = value
apply() if (children.size <= 1) {
return
}
forceApply()
} }
fun clear() { fun clear() {
if (children.size == 0) {
return
}
children.clear() children.clear()
forceApply()
} }
override fun forceRender(offset: Vec2i, z: Int, consumer: GUIVertexConsumer): Int { override fun forceRender(offset: Vec2i, z: Int, consumer: GUIVertexConsumer): Int {
@ -103,14 +108,15 @@ open class RowLayout(
element.parent = this element.parent = this
children += element children += element
forceApply() // ToDo: Optimize: Keep current layout, just add the element without redoing stuff
element.checkSilentApply()
apply() // ToDo: Optimize
parent?.onChildChange(this)
} }
@Synchronized @Synchronized
override fun silentApply() { override fun forceSilentApply() {
for (child in children) {
child.silentApply()
}
val maxSize = maxSize val maxSize = maxSize
val size = margin.offset val size = margin.offset
val prefSize = margin.spaceSize val prefSize = margin.spaceSize
@ -164,13 +170,6 @@ open class RowLayout(
this.size = size this.size = size
} }
override fun checkSilentApply() {
silentApply()
for (child in children) {
child.checkSilentApply()
}
}
override fun tick() { override fun tick() {
super.tick() super.tick()

View File

@ -36,10 +36,10 @@ class ZLayout(hudRenderer: HUDRenderer) : Element(hudRenderer) {
return zOffset return zOffset
} }
override fun silentApply() { override fun forceSilentApply() {
var size = Vec2i.EMPTY var size = Vec2i.EMPTY
for (child in children.toSynchronizedList()) { for (child in children.toSynchronizedList()) {
child.checkSilentApply() child.silentApply()
size = size.max(child.size) size = size.max(child.size)
} }
this.size = size + margin.spaceSize this.size = size + margin.spaceSize
@ -47,12 +47,12 @@ class ZLayout(hudRenderer: HUDRenderer) : Element(hudRenderer) {
fun append(child: Element) { fun append(child: Element) {
children += child children += child
silentApply() forceApply()
} }
fun add(index: Int, child: Element) { fun add(index: Int, child: Element) {
children.add(index, child) children.add(index, child)
silentApply() forceApply()
} }
operator fun plusAssign(child: Element) = append(child) operator fun plusAssign(child: Element) = append(child)

View File

@ -60,12 +60,13 @@ class GridCell(
child.tick() child.tick()
} }
override fun checkSilentApply() { override fun silentApply(): Boolean {
child.checkSilentApply() return child.silentApply()
} }
override fun silentApply() { @Suppress("DEPRECATION")
child.silentApply() override fun forceSilentApply() {
child.forceSilentApply()
} }
override fun apply() { override fun apply() {

View File

@ -49,9 +49,11 @@ class GridLayout(hudRenderer: HUDRenderer, val grid: Vec2i) : Element(hudRendere
} }
override fun silentApply() { override fun forceSilentApply() {
// ToDo: This works with columns, but rows are not yet implemented // ToDo: This works with columns, but rows are not yet implemented
// ToDo: Balance width of the columns
/* /*
Calculate new grid layout (sizes) with the new size of the child Calculate new grid layout (sizes) with the new size of the child
Set the parent (for maxSize) Set the parent (for maxSize)
@ -150,15 +152,17 @@ class GridLayout(hudRenderer: HUDRenderer, val grid: Vec2i) : Element(hudRendere
} }
} }
override fun checkSilentApply() { override fun silentApply(): Boolean {
apply() // ToDo: Check
forceSilentApply()
applyOnlyChildren() applyOnlyChildren()
return true
} }
private fun applyOnlyChildren() { private fun applyOnlyChildren() {
for (x in 0 until grid.x) { for (x in 0 until grid.x) {
for (y in 0 until grid.y) { for (y in 0 until grid.y) {
children[x][y]?.checkSilentApply() children[x][y]?.silentApply()
} }
} }
} }

View File

@ -82,6 +82,6 @@ open class ImageElement(
return 1 return 1
} }
override fun silentApply() = Unit override fun forceSilentApply() = Unit
override fun apply() = Unit override fun silentApply(): Boolean = false
} }

View File

@ -22,6 +22,6 @@ open class SpacerElement(hudRenderer: HUDRenderer, override var size: Vec2i) : E
override fun forceRender(offset: Vec2i, z: Int, consumer: GUIVertexConsumer): Int = 0 override fun forceRender(offset: Vec2i, z: Int, consumer: GUIVertexConsumer): Int = 0
override fun silentApply() = Unit override fun silentApply(): Boolean = false
override fun apply() = Unit override fun forceSilentApply() = Unit
} }

View File

@ -38,7 +38,6 @@ open class TextElement(
parent: Element? = null, parent: Element? = null,
) : LabeledElement(hudRenderer) { ) : LabeledElement(hudRenderer) {
private var previousMaxSize = Vec2i.EMPTY private var previousMaxSize = Vec2i.EMPTY
private var preparedSize = Vec2i.EMPTY
var renderInfo = TextRenderInfo() var renderInfo = TextRenderInfo()
override var text: Any = text override var text: Any = text
@ -69,7 +68,7 @@ open class TextElement(
textComponent = ChatComponent.of(text) textComponent = ChatComponent.of(text)
} }
override fun silentApply() { override fun forceSilentApply() {
val maxSize = maxSize val maxSize = maxSize
val size = Vec2i.EMPTY val size = Vec2i.EMPTY
if (!emptyMessage) { if (!emptyMessage) {
@ -83,26 +82,10 @@ open class TextElement(
this.previousMaxSize = maxSize this.previousMaxSize = maxSize
this.cacheUpToDate = false this.cacheUpToDate = false
this.size = size this.size = size
preparedSize = size
} }
override fun onChildChange(child: Element?) = error("A TextElement can not have a child!") override fun onChildChange(child: Element?) = error("A TextElement can not have a child!")
override fun checkSilentApply() {
val maxSize = maxSize
if (previousMaxSize == maxSize) {
// no change in size
return
}
val prefSize = prefSize
if (preparedSize.x < prefSize.x || preparedSize.x > maxSize.x) {
return silentApply()
}
if (preparedSize.y < prefSize.y || preparedSize.y > maxSize.y) {
return silentApply()
}
}
override fun forceRender(offset: Vec2i, z: Int, consumer: GUIVertexConsumer): Int { override fun forceRender(offset: Vec2i, z: Int, consumer: GUIVertexConsumer): Int {

View File

@ -62,7 +62,7 @@ class TextFlowElement(
} }
@Synchronized @Synchronized
override fun silentApply() { override fun forceSilentApply() {
val visibleLines: MutableList<TextFlowLineElement> = mutableListOf() val visibleLines: MutableList<TextFlowLineElement> = mutableListOf()
val maxSize = maxSize val maxSize = maxSize
val maxLines = maxSize.y / Font.TOTAL_CHAR_HEIGHT val maxLines = maxSize.y / Font.TOTAL_CHAR_HEIGHT
@ -118,7 +118,7 @@ class TextFlowElement(
messages.removeLast() messages.removeLast()
} }
messages.add(0, TextFlowTextElement(message)) messages.add(0, TextFlowTextElement(message))
apply() forceApply()
} }
operator fun plusAssign(message: ChatComponent) = addMessage(message) operator fun plusAssign(message: ChatComponent) = addMessage(message)
@ -128,7 +128,7 @@ class TextFlowElement(
for (line in visibleLines) { for (line in visibleLines) {
if (currentTime - line.text.addTime > messageExpireTime) { if (currentTime - line.text.addTime > messageExpireTime) {
apply() forceApply()
return return
} }
} }
@ -138,15 +138,6 @@ class TextFlowElement(
checkExpiredLines() checkExpiredLines()
} }
override fun checkSilentApply() {
val maxSize = maxSize
if (maxSize.x >= prefMaxSize.x && maxSize.y >= prefMaxSize.y) {
// Size did not change, skip
return
}
silentApply()
}
private data class TextFlowTextElement( private data class TextFlowTextElement(
val text: ChatComponent, val text: ChatComponent,
val addTime: Long = System.currentTimeMillis(), val addTime: Long = System.currentTimeMillis(),

View File

@ -93,7 +93,7 @@ class HUDRenderer(
matrixChange = true matrixChange = true
for (element in hudElements.toSynchronizedMap().values) { for (element in hudElements.toSynchronizedMap().values) {
element.layout?.checkSilentApply() element.layout?.silentApply()
element.apply() element.apply()
} }
}) })

View File

@ -37,10 +37,14 @@ class HotbarBaseElement(hudRenderer: HUDRenderer) : Element(hudRenderer) {
frame.render(offset + it.start - HORIZONTAL_MARGIN + FRAME_OFFSET, z + 1, consumer) frame.render(offset + it.start - HORIZONTAL_MARGIN + FRAME_OFFSET, z + 1, consumer)
} }
return 2 // bar + frame ToDo: Item rendering // ToDo: Item rendering
return 2 // bar + frame
} }
override fun silentApply() {} // No need to apply anything, has always the same size
override fun silentApply(): Boolean = false
override fun forceSilentApply() {}
companion object { companion object {
private val BASE = "minecraft:hotbar_base".toResourceLocation() private val BASE = "minecraft:hotbar_base".toResourceLocation()

View File

@ -52,12 +52,12 @@ class HotbarElement(hudRenderer: HUDRenderer) : Element(hudRenderer) {
topRight += hunger topRight += hunger
silentApply() forceSilentApply()
} }
override fun forceRender(offset: Vec2i, z: Int, consumer: GUIVertexConsumer): Int { override fun forceRender(offset: Vec2i, z: Int, consumer: GUIVertexConsumer): Int {
// ToDo: Do not apply every frame // ToDo: Do not apply every frame
silentApply() forceSilentApply()
var maxZ = 0 var maxZ = 0
val maxSize = topLeft.size.max(topRight.size) val maxSize = topLeft.size.max(topRight.size)
@ -73,9 +73,9 @@ class HotbarElement(hudRenderer: HUDRenderer) : Element(hudRenderer) {
return maxZ return maxZ
} }
override fun silentApply() { override fun forceSilentApply() {
for (element in renderElements) { for (element in renderElements) {
element.checkSilentApply() element.silentApply()
} }
size = base.size + Vec2i(0, max(topLeft.size.y, topRight.size.y)) + Vec2i(0, experience.size.y) size = base.size + Vec2i(0, max(topLeft.size.y, topRight.size.y)) + Vec2i(0, experience.size.y)

View File

@ -72,7 +72,11 @@ class HotbarExperienceBarElement(hudRenderer: HUDRenderer) : Element(hudRenderer
return 2 + TextElement.LAYERS // background + foreground + text(level) return 2 + TextElement.LAYERS // background + foreground + text(level)
} }
override fun silentApply() { override fun forceSilentApply() {
silentApply()
}
override fun silentApply(): Boolean {
val jumping = false // ToDo val jumping = false // ToDo
if (!jumping) { if (!jumping) {
@ -82,12 +86,10 @@ class HotbarExperienceBarElement(hudRenderer: HUDRenderer) : Element(hudRenderer
this.jumping = jumping this.jumping = jumping
this.level = experienceCondition.level this.level = experienceCondition.level
cacheUpToDate = false cacheUpToDate = false
return true
} }
} }
} return false
override fun checkSilentApply() {
silentApply()
} }
companion object { companion object {

View File

@ -209,23 +209,9 @@ class HotbarHealthElement(hudRenderer: HUDRenderer) : Element(hudRenderer) {
return 2 return 2
} }
override fun silentApply() { override fun forceSilentApply() {
// ToDo: Check if something changed
// ToDo: Notify parent?
val player = hudRenderer.connection.player
hardcode = hudRenderer.connection.world.hardcore
poison = poisonStatusEffect?.let { player.activeStatusEffects[it] != null } ?: false
wither = witherStatusEffect?.let { player.activeStatusEffects[it] != null } ?: false
frozen = player.ticksFrozen > 0
health = player.healthCondition.hp
absorptionsAmount = player.playerAbsorptionHearts // ToDo: This is (probably) calculated as effect instance
totalHealth = health + absorptionsAmount totalHealth = health + absorptionsAmount
maxHealth = player.getAttributeValue(DefaultStatusEffectAttributeNames.GENERIC_MAX_HEALTH).toFloat()
totalMaxHealth = maxHealth + absorptionsAmount totalMaxHealth = maxHealth + absorptionsAmount
totalMaxHearts = (totalMaxHealth / 2).ceil totalMaxHearts = (totalMaxHealth / 2).ceil
@ -239,10 +225,34 @@ class HotbarHealthElement(hudRenderer: HUDRenderer) : Element(hudRenderer) {
cacheUpToDate = false cacheUpToDate = false
} }
override fun checkSilentApply() { override fun silentApply(): Boolean {
silentApply() val player = hudRenderer.connection.player
} val hardcode = hudRenderer.connection.world.hardcore
val poison = poisonStatusEffect?.let { player.activeStatusEffects[it] != null } ?: false
val wither = witherStatusEffect?.let { player.activeStatusEffects[it] != null } ?: false
val frozen = player.ticksFrozen > 0
val health = player.healthCondition.hp
val absorptionsAmount = player.playerAbsorptionHearts // ToDo: This is (probably) calculated as effect instance
val maxHealth = player.getAttributeValue(DefaultStatusEffectAttributeNames.GENERIC_MAX_HEALTH).toFloat()
if (this.hardcode == hardcode && this.poison == poison && this.wither == wither && this.frozen == frozen && this.health == health && this.absorptionsAmount == absorptionsAmount && this.maxHealth == maxHealth) {
return false
}
this.hardcode = hardcode
this.poison = poison
this.wither = wither
this.frozen = frozen
this.health = health
this.absorptionsAmount = absorptionsAmount
this.maxHealth = maxHealth
forceSilentApply()
return true
}
companion object { companion object {
private const val HP_PER_ROW = 20 private const val HP_PER_ROW = 20

View File

@ -126,24 +126,8 @@ class HotbarHungerElement(hudRenderer: HUDRenderer) : Element(hudRenderer) {
return 2 return 2
} }
override fun silentApply() { override fun forceSilentApply() {
val healthCondition = hudRenderer.connection.player.healthCondition cacheUpToDate = false
if (hunger != healthCondition.hunger) {
hunger = healthCondition.hunger
cacheUpToDate = false
}
if (saturation != healthCondition.saturation) {
saturation = healthCondition.saturation
cacheUpToDate = false
}
val hungerEffect = hudRenderer.connection.player.activeStatusEffects.contains(hungerStatusEffect)
if (this.hungerEffect != hungerEffect) {
this.hungerEffect = hungerEffect
cacheUpToDate = false
}
} }
override fun tick() { override fun tick() {
@ -154,8 +138,24 @@ class HotbarHungerElement(hudRenderer: HUDRenderer) : Element(hudRenderer) {
animate = healthCondition.saturation <= 0.0f && ticks++ % (healthCondition.hunger * 3 + 1) == 0 animate = healthCondition.saturation <= 0.0f && ticks++ % (healthCondition.hunger * 3 + 1) == 0
} }
override fun checkSilentApply() { override fun silentApply(): Boolean {
silentApply() val healthCondition = hudRenderer.connection.player.healthCondition
val hunger = healthCondition.hunger
val saturation = healthCondition.saturation
val hungerEffect = hudRenderer.connection.player.activeStatusEffects.contains(hungerStatusEffect)
if (this.hunger == hunger && this.saturation == saturation && this.hungerEffect == hungerEffect) {
return false
}
this.hunger = hunger
this.saturation = saturation
this.hungerEffect = hungerEffect
forceSilentApply()
return true
} }
companion object { companion object {

View File

@ -26,7 +26,7 @@ class HotbarProtectionElement(hudRenderer: HUDRenderer) : Element(hudRenderer) {
private val fullProtection = hudRenderer.atlasManager["minecraft:full_protection"]!! private val fullProtection = hudRenderer.atlasManager["minecraft:full_protection"]!!
init { init {
silentApply() forceSilentApply()
} }
private var protection = 0.0f private var protection = 0.0f
@ -55,23 +55,27 @@ class HotbarProtectionElement(hudRenderer: HUDRenderer) : Element(hudRenderer) {
return 1 return 1
} }
override fun checkSilentApply() { override fun silentApply(): Boolean {
silentApply()
}
override fun silentApply() {
val protection = hudRenderer.connection.player.protectionLevel // ToDo: Check for equipment change val protection = hudRenderer.connection.player.protectionLevel // ToDo: Check for equipment change
if (this.protection == protection) { if (this.protection == protection) {
return return false
} }
size = if (protection <= 0.0f) { this.protection = protection
forceSilentApply()
return true
}
override fun forceSilentApply() {
size = if (protection <= 0.0f) { // ToDo: This notifies the parent, should we really notify it in silentApply?
Vec2i.EMPTY Vec2i.EMPTY
} else { } else {
SIZE SIZE
} }
this.protection = protection
cacheUpToDate = false cacheUpToDate = false
} }

View File

@ -55,7 +55,7 @@ class TabListElement(hudRenderer: HUDRenderer) : Element(hudRenderer) {
val size = size val size = size
header.size.let { header.size.let {
header.checkSilentApply() header.silentApply()
header.render(offset + Vec2i(HorizontalAlignments.CENTER.getOffset(size.x, it.x), 0), z, consumer) header.render(offset + Vec2i(HorizontalAlignments.CENTER.getOffset(size.x, it.x), 0), z, consumer)
offset.y += it.y offset.y += it.y
} }
@ -88,7 +88,8 @@ class TabListElement(hudRenderer: HUDRenderer) : Element(hudRenderer) {
return TextElement.LAYERS + 1 // ToDo return TextElement.LAYERS + 1 // ToDo
} }
override fun silentApply() { override fun forceSilentApply() {
// ToDo: There are still some items shown, that don't even exist (anymore?)
val size = Vec2i.EMPTY val size = Vec2i.EMPTY
size.y += header.size.y size.y += header.size.y
@ -96,6 +97,7 @@ class TabListElement(hudRenderer: HUDRenderer) : Element(hudRenderer) {
val toRender: MutableList<TabListEntryElement> = mutableListOf() val toRender: MutableList<TabListEntryElement> = mutableListOf()
// ToDo: Sorting isn't working correct: java.lang.IllegalArgumentException: Comparison method violates its general contract! // ToDo: Sorting isn't working correct: java.lang.IllegalArgumentException: Comparison method violates its general contract!
// Probably a threading issue
val tabListItems = hudRenderer.connection.tabList.tabListItemsByUUID.toSynchronizedMap().entries.sortedWith { a, b -> a.value.compareTo(b.value) } val tabListItems = hudRenderer.connection.tabList.tabListItemsByUUID.toSynchronizedMap().entries.sortedWith { a, b -> a.value.compareTo(b.value) }
val previousSize = Vec2i(size) val previousSize = Vec2i(size)
@ -161,10 +163,12 @@ class TabListElement(hudRenderer: HUDRenderer) : Element(hudRenderer) {
cacheUpToDate = false cacheUpToDate = false
} }
override fun checkSilentApply() { override fun silentApply(): Boolean {
// ToDo: Check for changes
for (element in toRender) { for (element in toRender) {
element.checkSilentApply() element.silentApply()
} }
return true
} }

View File

@ -14,7 +14,6 @@
package de.bixilon.minosoft.gui.rendering.gui.hud.elements.tab package de.bixilon.minosoft.gui.rendering.gui.hud.elements.tab
import de.bixilon.minosoft.data.player.tab.TabListItem import de.bixilon.minosoft.data.player.tab.TabListItem
import de.bixilon.minosoft.data.text.BaseComponent
import de.bixilon.minosoft.data.text.ChatComponent import de.bixilon.minosoft.data.text.ChatComponent
import de.bixilon.minosoft.data.text.RGBColor import de.bixilon.minosoft.data.text.RGBColor
import de.bixilon.minosoft.gui.rendering.gui.elements.Element import de.bixilon.minosoft.gui.rendering.gui.elements.Element
@ -45,8 +44,8 @@ class TabListEntryElement(
private val nameElement = TextElement(hudRenderer, "", background = false, parent = this) private val nameElement = TextElement(hudRenderer, "", background = false, parent = this)
private lateinit var pingElement: ImageElement private lateinit var pingElement: ImageElement
private var lastDisplayName: ChatComponent? = null private var displayName: ChatComponent = ChatComponent.EMPTY
private var lastPing = -1 private var ping = -1
override var prefSize: Vec2i = Vec2i.EMPTY override var prefSize: Vec2i = Vec2i.EMPTY
override var prefMaxSize: Vec2i override var prefMaxSize: Vec2i
@ -56,21 +55,18 @@ class TabListEntryElement(
get() = maxSize get() = maxSize
set(value) {} set(value) {}
private var forcePrepare = true
var width: Int = width var width: Int = width
set(value) { set(value) {
if (value == field) { if (value == field) {
return return
} }
field = value field = value
forcePrepare = true forceApply()
apply()
} }
init { init {
background = ColorElement(hudRenderer, size, RGBColor(80, 80, 80, 130)) background = ColorElement(hudRenderer, size, RGBColor(80, 80, 80, 130))
silentApply() forceSilentApply()
} }
override fun forceRender(offset: Vec2i, z: Int, consumer: GUIVertexConsumer): Int { override fun forceRender(offset: Vec2i, z: Int, consumer: GUIVertexConsumer): Int {
@ -81,49 +77,38 @@ class TabListEntryElement(
return TextElement.LAYERS return TextElement.LAYERS
} }
override fun silentApply() { override fun forceSilentApply() {
val ping = item.ping // ToDo (Performance): If something changed, should we just prepare the changed
pingElement = ImageElement(hudRenderer, tabList.pingBarsAtlasElements[when {
ping < 0 -> 0
ping < 150 -> 5
ping < 300 -> 4
ping < 600 -> 3
ping < 1000 -> 2
else -> 1
}])
nameElement.prefMaxSize = Vec2i(max(0, maxSize.x - pingElement.size.x), HEIGHT)
if (forcePrepare || ping != lastPing) { nameElement.text = displayName
pingElement = ImageElement(hudRenderer, tabList.pingBarsAtlasElements[when {
ping < 0 -> 0
ping < 150 -> 5
ping < 300 -> 4
ping < 600 -> 3
ping < 1000 -> 2
else -> 1
}])
nameElement.prefMaxSize = Vec2i(max(0, maxSize.x - pingElement.size.x), HEIGHT)
lastPing = ping
}
val displayName = BaseComponent()
item.team?.prefix?.let {
displayName += it
}
displayName += item.displayName.apply {
// ToDo: Set correct formatting code
val color = item.team?.formattingCode
if (color is RGBColor) {
applyDefaultColor(color)
}
}
item.team?.suffix?.let {
displayName += it
}
if (forcePrepare || displayName !== lastDisplayName) {
nameElement.text = displayName
lastDisplayName = displayName
}
this.prefSize = Vec2i((PADDING * 2) + nameElement.prefSize.x + INNER_MARGIN + pingElement.prefSize.x, HEIGHT) this.prefSize = Vec2i((PADDING * 2) + nameElement.prefSize.x + INNER_MARGIN + pingElement.prefSize.x, HEIGHT)
background.size = size background.size = size
forcePrepare = false
cacheUpToDate = false cacheUpToDate = false
} }
override fun checkSilentApply() { override fun silentApply(): Boolean {
forcePrepare = true val ping = item.ping
val displayName = item.tabDisplayName
if (this.ping == ping && this.displayName == displayName) {
return false
}
this.ping = ping
this.displayName = displayName
forceSilentApply()
return true
} }

View File

@ -58,6 +58,8 @@ class TabListHUDElement(hudRenderer: HUDRenderer) : HUDElement<TabListElement>(h
// ToDo: Cache more? // ToDo: Cache more?
layout.apply() layout.apply()
}) })
// ToDo: Also check team changes, scoreboard changes, etc
} }

View File

@ -60,6 +60,14 @@ object Vec2Util {
return max return max
} }
infix fun Vec2i.isSmaller(other: Vec2i): Boolean {
return this.x < other.x || this.y < other.y
}
infix fun Vec2i.isGreater(other: Vec2i): Boolean {
return this.x > other.x || this.y > other.y
}
fun Any?.toVec2i(default: Vec2i? = null): Vec2i { fun Any?.toVec2i(default: Vec2i? = null): Vec2i {
return when (this) { return when (this) {

View File

@ -14,6 +14,7 @@ package de.bixilon.minosoft.modding.event.events.annotations
import de.bixilon.minosoft.modding.loading.Priorities import de.bixilon.minosoft.modding.loading.Priorities
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME) @Retention(AnnotationRetention.RUNTIME)
annotation class EventHandler( annotation class EventHandler(
val ignoreCancelled: Boolean = false, val ignoreCancelled: Boolean = false,