mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-12 17:07:55 -04:00
hud: wip hotbar
This commit is contained in:
parent
758142d257
commit
27e36e4971
@ -563,6 +563,9 @@ class LocalPlayerEntity(
|
|||||||
fovMultiplier.value = 1.0 + MMath.clamp(walkingSpeed * 1.9, -2.0, 2.0)
|
fovMultiplier.value = 1.0 + MMath.clamp(walkingSpeed * 1.9, -2.0, 2.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val health: Double
|
||||||
|
get() = healthCondition.hp.toDouble()
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val CLIMBABLE_TAG = "minecraft:climbable".toResourceLocation()
|
private val CLIMBABLE_TAG = "minecraft:climbable".toResourceLocation()
|
||||||
private val SOUL_SPEED_BLOCKS = "minecraft:soul_speed_blocks".toResourceLocation()
|
private val SOUL_SPEED_BLOCKS = "minecraft:soul_speed_blocks".toResourceLocation()
|
||||||
|
@ -25,4 +25,6 @@ object DefaultStatusEffects {
|
|||||||
val DOLPHINS_GRACE = "minecraft:dolphins_grace".toResourceLocation()
|
val DOLPHINS_GRACE = "minecraft:dolphins_grace".toResourceLocation()
|
||||||
val NIGHT_VISION = "minecraft:night_vision".toResourceLocation()
|
val NIGHT_VISION = "minecraft:night_vision".toResourceLocation()
|
||||||
val CONDUIT_POWER = "minecraft:conduit_power".toResourceLocation()
|
val CONDUIT_POWER = "minecraft:conduit_power".toResourceLocation()
|
||||||
|
val WITHER = "minecraft:wither".toResourceLocation()
|
||||||
|
val POISON = "minecraft:poison".toResourceLocation()
|
||||||
}
|
}
|
||||||
|
@ -168,7 +168,7 @@ class RenderWindow(
|
|||||||
textureManager.staticTextures.createTexture(RenderConstants.DEBUG_TEXTURE_RESOURCE_LOCATION)
|
textureManager.staticTextures.createTexture(RenderConstants.DEBUG_TEXTURE_RESOURCE_LOCATION)
|
||||||
WHITE_TEXTURE = TextureLikeTexture(
|
WHITE_TEXTURE = TextureLikeTexture(
|
||||||
texture = textureManager.staticTextures.createTexture(ResourceLocation("minosoft:textures/white.png")),
|
texture = textureManager.staticTextures.createTexture(ResourceLocation("minosoft:textures/white.png")),
|
||||||
uvStart = Vec2(0, 0),
|
uvStart = Vec2(0.0f, 0.0f),
|
||||||
uvEnd = Vec2(0.001f, 0.001f),
|
uvEnd = Vec2(0.001f, 0.001f),
|
||||||
size = Vec2i(16, 16)
|
size = Vec2i(16, 16)
|
||||||
)
|
)
|
||||||
|
@ -71,6 +71,8 @@ open class ImageElement(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var matrix: Mat4 = hudRenderer.matrix
|
private var matrix: Mat4 = hudRenderer.matrix
|
||||||
|
private var lastOffset: Vec2i = Vec2i(-1, -1)
|
||||||
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
this.size = size
|
this.size = size
|
||||||
@ -82,13 +84,14 @@ open class ImageElement(
|
|||||||
|
|
||||||
override fun render(offset: Vec2i, z: Int, consumer: GUIVertexConsumer): Int {
|
override fun render(offset: Vec2i, z: Int, consumer: GUIVertexConsumer): Int {
|
||||||
val matrix = hudRenderer.matrix
|
val matrix = hudRenderer.matrix
|
||||||
if (matrix == this.matrix && cacheUpToDate) {
|
if (offset == lastOffset && matrix == this.matrix && cacheUpToDate) {
|
||||||
consumer.addCache(cache)
|
consumer.addCache(cache)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
val cache = GUIMeshCache(matrix, GUIMesh.GUIMeshStruct.FLOATS_PER_VERTEX * 6)
|
val cache = GUIMeshCache(matrix, GUIMesh.GUIMeshStruct.FLOATS_PER_VERTEX * 6)
|
||||||
cache.addQuad(offset, offset + size, z, texture, uvStart, uvEnd, tint)
|
cache.addQuad(offset, offset + size, z, texture, uvStart, uvEnd, tint)
|
||||||
|
|
||||||
|
this.lastOffset = offset
|
||||||
this.matrix = matrix
|
this.matrix = matrix
|
||||||
this.cache = cache
|
this.cache = cache
|
||||||
this.cacheUpToDate = true
|
this.cacheUpToDate = true
|
||||||
|
@ -23,6 +23,7 @@ import de.bixilon.minosoft.gui.rendering.Renderer
|
|||||||
import de.bixilon.minosoft.gui.rendering.RendererBuilder
|
import de.bixilon.minosoft.gui.rendering.RendererBuilder
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.hud.atlas.HUDAtlasManager
|
import de.bixilon.minosoft.gui.rendering.gui.hud.atlas.HUDAtlasManager
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.*
|
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.*
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.hotbar.HotbarHUDElement
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.tab.TabListHUDElement
|
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.tab.TabListHUDElement
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIMesh
|
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIMesh
|
||||||
import de.bixilon.minosoft.gui.rendering.modding.events.ResizeWindowEvent
|
import de.bixilon.minosoft.gui.rendering.modding.events.ResizeWindowEvent
|
||||||
@ -80,6 +81,7 @@ class HUDRenderer(
|
|||||||
}
|
}
|
||||||
registerElement(TabListHUDElement)
|
registerElement(TabListHUDElement)
|
||||||
registerElement(BreakProgressHUDElement)
|
registerElement(BreakProgressHUDElement)
|
||||||
|
registerElement(HotbarHUDElement)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun init() {
|
override fun init() {
|
||||||
|
@ -21,7 +21,7 @@ class HUDAtlasElement(
|
|||||||
override val texture: AbstractTexture,
|
override val texture: AbstractTexture,
|
||||||
val start: Vec2i,
|
val start: Vec2i,
|
||||||
val end: Vec2i,
|
val end: Vec2i,
|
||||||
val slots: Map<Int, Vec2Binding<Int>>, // ToDo: Use an array?
|
val slots: Map<Int, Vec2iBinding>, // ToDo: Use an array?
|
||||||
) : TextureLike {
|
) : TextureLike {
|
||||||
override val size: Vec2i = end - start
|
override val size: Vec2i = end - start
|
||||||
override lateinit var uvStart: Vec2
|
override lateinit var uvStart: Vec2
|
||||||
|
@ -51,12 +51,12 @@ class HUDAtlasManager(private val hudRenderer: HUDRenderer) {
|
|||||||
val texture = hudRenderer.renderWindow.textureManager.staticTextures.createTexture(versionData["texture"].toResourceLocation())
|
val texture = hudRenderer.renderWindow.textureManager.staticTextures.createTexture(versionData["texture"].toResourceLocation())
|
||||||
val start = versionData["start"].toVec2i()
|
val start = versionData["start"].toVec2i()
|
||||||
val end = versionData["end"].toVec2i()
|
val end = versionData["end"].toVec2i()
|
||||||
val slots: MutableMap<Int, Vec2Binding<Int>> = mutableMapOf()
|
val slots: MutableMap<Int, Vec2iBinding> = mutableMapOf()
|
||||||
|
|
||||||
versionData["slots"]?.mapCast()?.let {
|
versionData["slots"]?.mapCast()?.let {
|
||||||
for ((slotId, slotData) in it) {
|
for ((slotId, slotData) in it) {
|
||||||
val slot = slotData.mapCast()!!
|
val slot = slotData.mapCast()!!
|
||||||
slots[slotId.toInt()] = Vec2Binding(
|
slots[slotId.toInt()] = Vec2iBinding(
|
||||||
start = slot["start"].toVec2i(),
|
start = slot["start"].toVec2i(),
|
||||||
end = slot["end"].toVec2i(),
|
end = slot["end"].toVec2i(),
|
||||||
)
|
)
|
||||||
@ -87,6 +87,10 @@ class HUDAtlasManager(private val hudRenderer: HUDRenderer) {
|
|||||||
return elements[resourceLocation]
|
return elements[resourceLocation]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
operator fun get(resourceLocation: String): HUDAtlasElement? {
|
||||||
|
return elements[resourceLocation.toResourceLocation()]
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val ATLAS_DATA = "minosoft:mapping/atlas.json".toResourceLocation()
|
private val ATLAS_DATA = "minosoft:mapping/atlas.json".toResourceLocation()
|
||||||
}
|
}
|
||||||
|
@ -13,9 +13,11 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.gui.rendering.gui.hud.atlas
|
package de.bixilon.minosoft.gui.rendering.gui.hud.atlas
|
||||||
|
|
||||||
import glm_.vec2.Vec2t
|
import glm_.vec2.Vec2i
|
||||||
|
|
||||||
data class Vec2Binding<T : Number>(
|
data class Vec2iBinding(
|
||||||
val start: Vec2t<T>,
|
val start: Vec2i,
|
||||||
val end: Vec2t<T>,
|
val end: Vec2i,
|
||||||
)
|
) {
|
||||||
|
val size = end - start
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Minosoft
|
||||||
|
* Copyright (C) 2021 Moritz Zwerger
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.bixilon.minosoft.gui.rendering.gui.hud.elements.hotbar
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.elements.Element
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.elements.primitive.ImageElement
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.hud.HUDRenderer
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
|
||||||
|
import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
||||||
|
import glm_.vec2.Vec2i
|
||||||
|
|
||||||
|
class HotbarBaseElement(hudRenderer: HUDRenderer) : Element(hudRenderer) {
|
||||||
|
private val baseAtlasElement = hudRenderer.atlasManager[BASE]!!
|
||||||
|
private val base = ImageElement(hudRenderer, baseAtlasElement)
|
||||||
|
private val frame = ImageElement(hudRenderer, hudRenderer.atlasManager[FRAME]!!, size = Vec2i(FRAME_SIZE))
|
||||||
|
|
||||||
|
override fun render(offset: Vec2i, z: Int, consumer: GUIVertexConsumer): Int {
|
||||||
|
base.render(offset + HORIZONTAL_MARGIN, z, consumer)
|
||||||
|
|
||||||
|
baseAtlasElement.slots[hudRenderer.connection.player.selectedHotbarSlot]?.let {
|
||||||
|
frame.render(offset + it.start - HORIZONTAL_MARGIN + FRAME_OFFSET, z + 1, consumer)
|
||||||
|
}
|
||||||
|
|
||||||
|
return 2 // bar + frame ToDo: Item rendering
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun silentApply() {
|
||||||
|
size = HOTBAR_BASE_SIZE + Vec2i(HORIZONTAL_MARGIN * 2, 1) // offset left and right; offset for the frame is just on top, not on the bottom
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val BASE = "minecraft:hotbar_base".toResourceLocation()
|
||||||
|
private val FRAME = "minecraft:hotbar_frame".toResourceLocation()
|
||||||
|
|
||||||
|
private val HOTBAR_BASE_SIZE = Vec2i(182, 22)
|
||||||
|
private const val FRAME_SIZE = 24
|
||||||
|
private const val HORIZONTAL_MARGIN = 1
|
||||||
|
private const val FRAME_OFFSET = -2 // FRAME_SIZE - HOTBAR_BASE_SIZE.y
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Minosoft
|
||||||
|
* Copyright (C) 2021 Moritz Zwerger
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.bixilon.minosoft.gui.rendering.gui.hud.elements.hotbar
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.elements.Element
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.hud.HUDRenderer
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
|
||||||
|
import glm_.vec2.Vec2i
|
||||||
|
import java.lang.Integer.max
|
||||||
|
|
||||||
|
class HotbarElement(hudRenderer: HUDRenderer) : Element(hudRenderer) {
|
||||||
|
private val base = HotbarBaseElement(hudRenderer)
|
||||||
|
private val health = HotbarHealthElement(hudRenderer)
|
||||||
|
|
||||||
|
|
||||||
|
init {
|
||||||
|
silentApply()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun render(offset: Vec2i, z: Int, consumer: GUIVertexConsumer): Int {
|
||||||
|
silentApply()
|
||||||
|
val initialOffset = Vec2i(offset)
|
||||||
|
var maxZ = 0
|
||||||
|
maxZ = max(maxZ, health.render(offset, z, consumer))
|
||||||
|
offset.y += health.size.y
|
||||||
|
maxZ = max(maxZ, base.render(offset, z, consumer))
|
||||||
|
|
||||||
|
return maxZ
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun silentApply() {
|
||||||
|
base.silentApply()
|
||||||
|
health.silentApply()
|
||||||
|
|
||||||
|
size = base.size + Vec2i(0, health.size.y)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Minosoft
|
||||||
|
* Copyright (C) 2021 Moritz Zwerger
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.bixilon.minosoft.gui.rendering.gui.hud.elements.hotbar
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.data.registries.ResourceLocation
|
||||||
|
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.util.KUtil.toResourceLocation
|
||||||
|
import glm_.vec2.Vec2i
|
||||||
|
|
||||||
|
class HotbarHUDElement(hudRenderer: HUDRenderer) : HUDElement<HotbarElement>(hudRenderer) {
|
||||||
|
private val connection = renderWindow.connection
|
||||||
|
override lateinit var layout: HotbarElement
|
||||||
|
|
||||||
|
|
||||||
|
override val layoutOffset: Vec2i
|
||||||
|
get() = Vec2i((hudRenderer.scaledSize.x - layout.size.x) / 2, hudRenderer.scaledSize.y - layout.size.y)
|
||||||
|
|
||||||
|
|
||||||
|
override fun init() {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun postInit() {
|
||||||
|
layout = HotbarElement(hudRenderer)
|
||||||
|
layout.prefMaxSize = Vec2i(-1, -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
companion object : HUDBuilder<HotbarHUDElement> {
|
||||||
|
override val RESOURCE_LOCATION: ResourceLocation = "minosoft:hotbar".toResourceLocation()
|
||||||
|
|
||||||
|
override fun build(hudRenderer: HUDRenderer): HotbarHUDElement {
|
||||||
|
return HotbarHUDElement(hudRenderer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,249 @@
|
|||||||
|
/*
|
||||||
|
* Minosoft
|
||||||
|
* Copyright (C) 2021 Moritz Zwerger
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.bixilon.minosoft.gui.rendering.gui.hud.elements.hotbar
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.data.registries.effects.DefaultStatusEffects
|
||||||
|
import de.bixilon.minosoft.data.registries.effects.attributes.DefaultStatusEffectAttributeNames
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.elements.Element
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.elements.primitive.ImageElement
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.hud.HUDRenderer
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.hud.atlas.HUDAtlasElement
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
|
||||||
|
import de.bixilon.minosoft.util.KUtil.decide
|
||||||
|
import de.bixilon.minosoft.util.KUtil.unsafeCast
|
||||||
|
import de.bixilon.minosoft.util.MMath.ceil
|
||||||
|
import glm_.vec2.Vec2i
|
||||||
|
|
||||||
|
class HotbarHealthElement(hudRenderer: HUDRenderer) : Element(hudRenderer) {
|
||||||
|
private val witherStatusEffect = hudRenderer.connection.registries.statusEffectRegistry[DefaultStatusEffects.WITHER]
|
||||||
|
private val poisonStatusEffect = hudRenderer.connection.registries.statusEffectRegistry[DefaultStatusEffects.POISON]
|
||||||
|
private val atlasManager = hudRenderer.atlasManager
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [normal|hardcore][normal|poison|wither][normal|damage][full|half]
|
||||||
|
*/
|
||||||
|
private val hearts = arrayOf(
|
||||||
|
arrayOf(
|
||||||
|
arrayOf(
|
||||||
|
arrayOf(
|
||||||
|
atlasManager["minecraft:normal_heart"],
|
||||||
|
atlasManager["minecraft:half_normal_heart"],
|
||||||
|
),
|
||||||
|
arrayOf(
|
||||||
|
atlasManager["minecraft:normal_damage_heart"],
|
||||||
|
atlasManager["minecraft:half_normal_damage_heart"],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
arrayOf(
|
||||||
|
arrayOf(
|
||||||
|
atlasManager["minecraft:poison_heart"],
|
||||||
|
atlasManager["minecraft:half_poison_heart"],
|
||||||
|
),
|
||||||
|
arrayOf(
|
||||||
|
atlasManager["minecraft:poison_damage_heart"],
|
||||||
|
atlasManager["minecraft:half_poison_damage_heart"],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
arrayOf(
|
||||||
|
arrayOf(
|
||||||
|
atlasManager["minecraft:wither_heart"],
|
||||||
|
atlasManager["minecraft:half_wither_heart"],
|
||||||
|
),
|
||||||
|
arrayOf(
|
||||||
|
atlasManager["minecraft:wither_damage_heart"],
|
||||||
|
atlasManager["minecraft:half_wither_damage_heart"],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
arrayOf(
|
||||||
|
arrayOf(
|
||||||
|
arrayOf(
|
||||||
|
atlasManager["minecraft:hardcore_normal_heart"],
|
||||||
|
atlasManager["minecraft:hardcore_half_normal_heart"],
|
||||||
|
),
|
||||||
|
arrayOf(
|
||||||
|
atlasManager["minecraft:hardcore_normal_damage_heart"],
|
||||||
|
atlasManager["minecraft:hardcore_half_normal_damage_heart"],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
arrayOf(
|
||||||
|
arrayOf(
|
||||||
|
atlasManager["minecraft:hardcore_poison_heart"],
|
||||||
|
atlasManager["minecraft:hardcore_half_poison_heart"],
|
||||||
|
),
|
||||||
|
arrayOf(
|
||||||
|
atlasManager["minecraft:hardcore_poison_damage_heart"],
|
||||||
|
atlasManager["minecraft:hardcore_half_poison_damage_heart"],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
arrayOf(
|
||||||
|
arrayOf(
|
||||||
|
atlasManager["minecraft:hardcore_wither_heart"],
|
||||||
|
atlasManager["minecraft:hardcore_half_wither_heart"],
|
||||||
|
),
|
||||||
|
arrayOf(
|
||||||
|
atlasManager["minecraft:hardcore_wither_damage_heart"],
|
||||||
|
atlasManager["minecraft:hardcore_half_wither_damage_heart"],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [normal|hardcore][full|half]
|
||||||
|
*/
|
||||||
|
private val absorptionHearts = arrayOf(
|
||||||
|
arrayOf(
|
||||||
|
atlasManager["minecraft:absorption_heart"],
|
||||||
|
atlasManager["minecraft:half_absorption_heart"],
|
||||||
|
),
|
||||||
|
arrayOf(
|
||||||
|
atlasManager["minecraft:hardcore_absorption_heart"],
|
||||||
|
atlasManager["minecraft:hardcore_half_absorption_heart"],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [normal|hardcore][full|half]
|
||||||
|
*/
|
||||||
|
private val frozenHearts = arrayOf(
|
||||||
|
arrayOf(
|
||||||
|
atlasManager["minecraft:frozen_heart"],
|
||||||
|
atlasManager["minecraft:half_frozen_heart"],
|
||||||
|
),
|
||||||
|
arrayOf(
|
||||||
|
atlasManager["minecraft:hardcore_frozen_heart"],
|
||||||
|
atlasManager["minecraft:hardcore_half_frozen_heart"],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
private val whiteHeartContainer = atlasManager["minecraft:white_heart_container"]
|
||||||
|
private val blackHeartContainer = atlasManager["minecraft:black_heart_container"]
|
||||||
|
|
||||||
|
private var hardcode = false
|
||||||
|
private var poison = false
|
||||||
|
private var wither = false
|
||||||
|
private var frozen = false
|
||||||
|
|
||||||
|
private var health = 0.0f
|
||||||
|
private var absorptionsAmount = 0.0f
|
||||||
|
private var totalHealth = 0.0f
|
||||||
|
|
||||||
|
private var maxHealth = 0.0f
|
||||||
|
private var totalMaxHealth = 0.0f
|
||||||
|
|
||||||
|
private var totalMaxHearts = 0
|
||||||
|
private var rows = 0
|
||||||
|
|
||||||
|
override fun render(offset: Vec2i, z: Int, consumer: GUIVertexConsumer): Int {
|
||||||
|
blackHeartContainer ?: return 0
|
||||||
|
whiteHeartContainer ?: return 0
|
||||||
|
|
||||||
|
// ToDo: Damage animation, regeneration, caching
|
||||||
|
for (heart in 0 until totalMaxHearts) {
|
||||||
|
val row = heart / HEARTS_PER_ROW
|
||||||
|
val column = heart % HEARTS_PER_ROW
|
||||||
|
|
||||||
|
val image = ImageElement(hudRenderer, blackHeartContainer)
|
||||||
|
|
||||||
|
image.render(offset + Vec2i(column, (rows - 1) - row) * HEART_SIZE, z, consumer)
|
||||||
|
}
|
||||||
|
|
||||||
|
val hardcoreIndex = hardcode.decide(1, 0)
|
||||||
|
|
||||||
|
var healthLeft = totalHealth
|
||||||
|
var heart = 0
|
||||||
|
|
||||||
|
while (healthLeft > 0.5f) {
|
||||||
|
val row = heart / HEARTS_PER_ROW
|
||||||
|
val column = heart % HEARTS_PER_ROW
|
||||||
|
|
||||||
|
|
||||||
|
var selectArray: Array<*>? = null
|
||||||
|
|
||||||
|
var normalHeart = false
|
||||||
|
|
||||||
|
if (healthLeft <= absorptionsAmount) {
|
||||||
|
selectArray = absorptionHearts[hardcoreIndex]
|
||||||
|
} else {
|
||||||
|
selectArray = hearts[hardcoreIndex]
|
||||||
|
|
||||||
|
// heart type
|
||||||
|
selectArray = selectArray[when {
|
||||||
|
poison -> 1
|
||||||
|
wither -> 2
|
||||||
|
else -> {
|
||||||
|
normalHeart = true
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
|
||||||
|
// ToDo: damage heart
|
||||||
|
selectArray = selectArray[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frozen && normalHeart) {
|
||||||
|
selectArray = frozenHearts[hardcoreIndex]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
val halfHeart = healthLeft < 1.5f
|
||||||
|
val image = when {
|
||||||
|
halfHeart -> selectArray.unsafeCast<Array<HUDAtlasElement?>>()[1]?.let { ImageElement(hudRenderer, it) }
|
||||||
|
else -> selectArray.unsafeCast<Array<HUDAtlasElement?>>()[0]?.let { ImageElement(hudRenderer, it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
image?.render(offset + Vec2i(column, (rows - 1) - row) * HEART_SIZE, z + 1, consumer)
|
||||||
|
|
||||||
|
heart++
|
||||||
|
healthLeft -= halfHeart.decide(1.0f, 2.0f)
|
||||||
|
}
|
||||||
|
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun silentApply() {
|
||||||
|
blackHeartContainer ?: return
|
||||||
|
whiteHeartContainer ?: return
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
maxHealth = player.getAttributeValue(DefaultStatusEffectAttributeNames.GENERIC_MAX_HEALTH).toFloat()
|
||||||
|
totalMaxHealth = maxHealth + absorptionsAmount
|
||||||
|
|
||||||
|
totalMaxHearts = (totalMaxHealth / 2).ceil
|
||||||
|
|
||||||
|
rows = totalMaxHearts / HEARTS_PER_ROW
|
||||||
|
if (totalMaxHearts % HP_PER_ROW != 0) {
|
||||||
|
rows++
|
||||||
|
}
|
||||||
|
|
||||||
|
size = Vec2i(HEARTS_PER_ROW, rows) * HEART_SIZE
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val HP_PER_ROW = 20
|
||||||
|
private const val HEARTS_PER_ROW = HP_PER_ROW / 2
|
||||||
|
private val HEART_SIZE = Vec2i(8, 9)
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user