mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-18 11:54:59 -04:00
fixes, wip health bar
This commit is contained in:
parent
97c3e3232e
commit
4aeb127f6b
@ -21,6 +21,7 @@ import de.bixilon.minosoft.gui.rendering.RenderConstants
|
|||||||
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
|
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.atlas.HUDAtlasElement
|
import de.bixilon.minosoft.gui.rendering.hud.atlas.HUDAtlasElement
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.elements.HUDElement
|
import de.bixilon.minosoft.gui.rendering.hud.elements.HUDElement
|
||||||
|
import de.bixilon.minosoft.gui.rendering.hud.elements.primitive.HealthBar
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.elements.primitive.ImageElement
|
import de.bixilon.minosoft.gui.rendering.hud.elements.primitive.ImageElement
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.elements.primitive.ProgressBar
|
import de.bixilon.minosoft.gui.rendering.hud.elements.primitive.ProgressBar
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.elements.primitive.TextElement
|
import de.bixilon.minosoft.gui.rendering.hud.elements.primitive.TextElement
|
||||||
@ -28,6 +29,7 @@ import de.bixilon.minosoft.modding.event.EventInvokerCallback
|
|||||||
import de.bixilon.minosoft.modding.event.events.ChangeGameStateEvent
|
import de.bixilon.minosoft.modding.event.events.ChangeGameStateEvent
|
||||||
import de.bixilon.minosoft.modding.event.events.ExperienceChangeEvent
|
import de.bixilon.minosoft.modding.event.events.ExperienceChangeEvent
|
||||||
import de.bixilon.minosoft.modding.event.events.HeldItemChangeEvent
|
import de.bixilon.minosoft.modding.event.events.HeldItemChangeEvent
|
||||||
|
import de.bixilon.minosoft.modding.event.events.UpdateHealthEvent
|
||||||
import de.bixilon.minosoft.protocol.packets.clientbound.play.PacketChangeGameState
|
import de.bixilon.minosoft.protocol.packets.clientbound.play.PacketChangeGameState
|
||||||
import glm_.vec2.Vec2
|
import glm_.vec2.Vec2
|
||||||
|
|
||||||
@ -40,6 +42,8 @@ class HotbarHUDElement(
|
|||||||
private lateinit var experienceBar: ProgressBar
|
private lateinit var experienceBar: ProgressBar
|
||||||
private lateinit var levelText: TextElement
|
private lateinit var levelText: TextElement
|
||||||
|
|
||||||
|
private lateinit var healthBar: HealthBar
|
||||||
|
|
||||||
|
|
||||||
override fun init() {
|
override fun init() {
|
||||||
hotbarBaseAtlasElement = hudRenderer.hudAtlasElements[ResourceLocation("minecraft:hotbar_base")]!!
|
hotbarBaseAtlasElement = hudRenderer.hudAtlasElements[ResourceLocation("minecraft:hotbar_base")]!!
|
||||||
@ -55,6 +59,19 @@ class HotbarHUDElement(
|
|||||||
|
|
||||||
levelText = TextElement(start = Vec2(), font = hudRenderer.renderWindow.font, background = false)
|
levelText = TextElement(start = Vec2(), font = hudRenderer.renderWindow.font, background = false)
|
||||||
|
|
||||||
|
healthBar = HealthBar(
|
||||||
|
Vec2(0, 0),
|
||||||
|
hudRenderer.hudAtlasElements[ResourceLocation("minecraft:black_heart_container")]!!,
|
||||||
|
hudRenderer.hudAtlasElements[ResourceLocation("minecraft:white_heart_container")]!!,
|
||||||
|
hudRenderer.hudAtlasElements[ResourceLocation("minecraft:half_red_heart")]!!,
|
||||||
|
hudRenderer.hudAtlasElements[ResourceLocation("minecraft:full_red_heart")]!!,
|
||||||
|
20.0f,
|
||||||
|
40.0f,
|
||||||
|
RenderConstants.HP_TEXT_COLOR,
|
||||||
|
hudRenderer.renderWindow.font,
|
||||||
|
5
|
||||||
|
)
|
||||||
|
|
||||||
registerEvents()
|
registerEvents()
|
||||||
|
|
||||||
prepare()
|
prepare()
|
||||||
@ -83,6 +100,10 @@ class HotbarHUDElement(
|
|||||||
}
|
}
|
||||||
prepare()
|
prepare()
|
||||||
})
|
})
|
||||||
|
hudRenderer.connection.registerEvent(EventInvokerCallback<UpdateHealthEvent> {
|
||||||
|
healthBar.value = it.health
|
||||||
|
prepare()
|
||||||
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,9 +118,15 @@ class HotbarHUDElement(
|
|||||||
|
|
||||||
|
|
||||||
if (hudRenderer.connection.player.gamemode != Gamemodes.CREATIVE) {
|
if (hudRenderer.connection.player.gamemode != Gamemodes.CREATIVE) {
|
||||||
// experience
|
healthBar.prepare()
|
||||||
levelText.start = Vec2((hotbarBaseAtlasElement.binding.size.x - levelText.size.x) / 2, elementList.size.y)
|
elementList.addChild(healthBar)
|
||||||
elementList.addChild(levelText)
|
|
||||||
|
|
||||||
|
if (hudRenderer.connection.player.level != 0) {
|
||||||
|
// experience
|
||||||
|
levelText.start = Vec2((hotbarBaseAtlasElement.binding.size.x - levelText.size.x) / 2, elementList.size.y - 3 * ELEMENT_PADDING)
|
||||||
|
elementList.addChild(levelText)
|
||||||
|
}
|
||||||
|
|
||||||
// experience bar
|
// experience bar
|
||||||
experienceBar.start.y = elementList.size.y - ELEMENT_PADDING
|
experienceBar.start.y = elementList.size.y - ELEMENT_PADDING
|
||||||
|
@ -27,13 +27,17 @@ open class ElementListElement(
|
|||||||
|
|
||||||
fun clear() {
|
fun clear() {
|
||||||
clearCache()
|
clearCache()
|
||||||
children.clear()
|
synchronized(children) {
|
||||||
|
children.clear()
|
||||||
|
}
|
||||||
recalculateSize()
|
recalculateSize()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addChild(child: Element) {
|
fun addChild(child: Element) {
|
||||||
child.parent = this
|
child.parent = this
|
||||||
children.add(child)
|
synchronized(children) {
|
||||||
|
children.add(child)
|
||||||
|
}
|
||||||
cache.clear()
|
cache.clear()
|
||||||
recalculateSize()
|
recalculateSize()
|
||||||
}
|
}
|
||||||
@ -50,8 +54,10 @@ open class ElementListElement(
|
|||||||
|
|
||||||
override fun clearCache() {
|
override fun clearCache() {
|
||||||
cache.clear()
|
cache.clear()
|
||||||
for (child in children) {
|
synchronized(children) {
|
||||||
child.clearCache()
|
for (child in children) {
|
||||||
|
child.clearCache()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,9 +90,12 @@ open class ElementListElement(
|
|||||||
override fun prepareCache(start: Vec2, scaleFactor: Float, matrix: Mat4, z: Int) {
|
override fun prepareCache(start: Vec2, scaleFactor: Float, matrix: Mat4, z: Int) {
|
||||||
val normalStart = addToStart(start, this.start * scaleFactor)
|
val normalStart = addToStart(start, this.start * scaleFactor)
|
||||||
|
|
||||||
for (child in children) {
|
|
||||||
child.checkCache(normalStart, scaleFactor, matrix, this.z + z)
|
synchronized(children) {
|
||||||
cache.addCache(child.cache)
|
for (child in children) {
|
||||||
|
child.checkCache(normalStart, scaleFactor, matrix, this.z + z)
|
||||||
|
cache.addCache(child.cache)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,135 @@
|
|||||||
|
/*
|
||||||
|
* 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.hud.elements.primitive
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.data.text.RGBColor
|
||||||
|
import de.bixilon.minosoft.data.text.TextComponent
|
||||||
|
import de.bixilon.minosoft.gui.rendering.font.Font
|
||||||
|
import de.bixilon.minosoft.gui.rendering.hud.atlas.HUDAtlasElement
|
||||||
|
import de.bixilon.minosoft.util.MMath
|
||||||
|
import glm_.mat4x4.Mat4
|
||||||
|
import glm_.vec2.Vec2
|
||||||
|
|
||||||
|
class HealthBar(
|
||||||
|
start: Vec2,
|
||||||
|
var blackHeartContainerAtlasElement: HUDAtlasElement,
|
||||||
|
var whiteHeartContainerAtlasElement: HUDAtlasElement,
|
||||||
|
var halfHartAtlasElement: HUDAtlasElement,
|
||||||
|
var hartAtlasElement: HUDAtlasElement,
|
||||||
|
var maxValue: Float,
|
||||||
|
var textReplaceValue: Float,
|
||||||
|
var textColor: RGBColor,
|
||||||
|
var font: Font,
|
||||||
|
z: Int = 1,
|
||||||
|
) : ElementListElement(start, z) {
|
||||||
|
private val singleHeartSize = blackHeartContainerAtlasElement.binding.size
|
||||||
|
private val width = singleHeartSize.x * MAX_HEARTS_IN_ROW
|
||||||
|
|
||||||
|
private val alternativeText = TextElement(font = font, start = Vec2(), background = false)
|
||||||
|
private var _value = 0.0f
|
||||||
|
var value: Float
|
||||||
|
get() = _value
|
||||||
|
set(value) {
|
||||||
|
_value = if (value < 0.0f) {
|
||||||
|
0.0f
|
||||||
|
} else {
|
||||||
|
value
|
||||||
|
}
|
||||||
|
cache.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun prepare() {
|
||||||
|
clear()
|
||||||
|
|
||||||
|
if (value >= textReplaceValue) {
|
||||||
|
alternativeText.text = TextComponent(value.toString()).setColor(textColor)
|
||||||
|
alternativeText.start = Vec2((width - alternativeText.size.x) / 2, 0)
|
||||||
|
|
||||||
|
addChild(alternativeText)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val offset = Vec2(0, 0)
|
||||||
|
val containerCount = (maxValue + 1.0f).toInt() / 2
|
||||||
|
|
||||||
|
// heart container
|
||||||
|
val rows = MMath.divideUp(containerCount, MAX_HEARTS_IN_ROW)
|
||||||
|
for (row in 0 until rows) {
|
||||||
|
val heartsToDraw = if (row == 0 && containerCount % MAX_HEARTS_IN_ROW != 0) {
|
||||||
|
containerCount % MAX_HEARTS_IN_ROW
|
||||||
|
} else {
|
||||||
|
MAX_HEARTS_IN_ROW
|
||||||
|
}
|
||||||
|
for (i in 0 until heartsToDraw) {
|
||||||
|
drawHeart(this.start + offset, blackHeartContainerAtlasElement, z)
|
||||||
|
|
||||||
|
offset.x += singleHeartSize.x - 1
|
||||||
|
}
|
||||||
|
offset.y += singleHeartSize.y
|
||||||
|
offset.x = 0.0f
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
offset.x = 0.0f
|
||||||
|
offset.y = 0.0f
|
||||||
|
val halfHeartCount = MMath.round10Up(value)
|
||||||
|
val fullHeartCount = halfHeartCount / 2
|
||||||
|
|
||||||
|
val addHalfHeart = halfHeartCount % 2 == 1
|
||||||
|
|
||||||
|
var currentHeart = fullHeartCount - 1
|
||||||
|
if (addHalfHeart) {
|
||||||
|
currentHeart += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
for (row in rows - 1 downTo 0) {
|
||||||
|
val heartsInRow = if (row == 0 && containerCount % MAX_HEARTS_IN_ROW != 0) {
|
||||||
|
containerCount % MAX_HEARTS_IN_ROW
|
||||||
|
} else {
|
||||||
|
MAX_HEARTS_IN_ROW
|
||||||
|
}
|
||||||
|
for (i in 0 until heartsInRow) {
|
||||||
|
|
||||||
|
if (currentHeart < 0) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentHeart == 0 && addHalfHeart) {
|
||||||
|
drawHeart(this.start + offset, halfHartAtlasElement, z + 1)
|
||||||
|
} else {
|
||||||
|
drawHeart(this.start + offset, hartAtlasElement, z + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
currentHeart--
|
||||||
|
offset.x += singleHeartSize.x - 1
|
||||||
|
}
|
||||||
|
offset.y += singleHeartSize.y
|
||||||
|
offset.x = 0.0f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun prepareCache(start: Vec2, scaleFactor: Float, matrix: Mat4, z: Int) {
|
||||||
|
prepare()
|
||||||
|
super.prepareCache(start, scaleFactor, matrix, z)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun drawHeart(elementStart: Vec2, element: HUDAtlasElement, z: Int) {
|
||||||
|
addChild(ImageElement(elementStart, elementStart + singleHeartSize, element, z))
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val MAX_HEARTS_IN_ROW = 10
|
||||||
|
}
|
||||||
|
}
|
@ -36,7 +36,7 @@ class TextElement(
|
|||||||
var sText: String
|
var sText: String
|
||||||
get() = text.message
|
get() = text.message
|
||||||
set(value) {
|
set(value) {
|
||||||
text = ChatComponent.valueOf(sText)
|
text = ChatComponent.valueOf(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
@ -59,7 +59,7 @@ class TextureArray(val textures: MutableList<Texture>) {
|
|||||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT)
|
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT)
|
||||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT)
|
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT)
|
||||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
|
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
|
||||||
// glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST) // ToDo: This breaks transparency again
|
// glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR) // ToDo: This breaks transparency again
|
||||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
|
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
|
||||||
|
|
||||||
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, maxWidth, maxHeight, textures.size, 0, GL_RGBA, GL_UNSIGNED_BYTE, null as ByteBuffer?)
|
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, maxWidth, maxHeight, textures.size, 0, GL_RGBA, GL_UNSIGNED_BYTE, null as ByteBuffer?)
|
||||||
|
@ -19,7 +19,7 @@ import de.bixilon.minosoft.protocol.packets.clientbound.play.PacketChangeGameSta
|
|||||||
/**
|
/**
|
||||||
* Fired when the player should spectate an entity
|
* Fired when the player should spectate an entity
|
||||||
*/
|
*/
|
||||||
public class ChangeGameStateEvent extends CancelableEvent {
|
public class ChangeGameStateEvent extends ConnectionEvent {
|
||||||
private final PacketChangeGameState.Reason reason;
|
private final PacketChangeGameState.Reason reason;
|
||||||
private final float value;
|
private final float value;
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ import de.bixilon.minosoft.protocol.packets.clientbound.play.PacketCollectItem;
|
|||||||
import static de.bixilon.minosoft.protocol.protocol.ProtocolVersions.V_16W32A;
|
import static de.bixilon.minosoft.protocol.protocol.ProtocolVersions.V_16W32A;
|
||||||
|
|
||||||
public class CollectItemAnimationEvent extends CancelableEvent {
|
public class CollectItemAnimationEvent extends CancelableEvent {
|
||||||
private final ItemEntity item;
|
private final Entity item;
|
||||||
private final Entity collector;
|
private final Entity collector;
|
||||||
private final int count;
|
private final int count;
|
||||||
|
|
||||||
@ -35,12 +35,12 @@ public class CollectItemAnimationEvent extends CancelableEvent {
|
|||||||
|
|
||||||
public CollectItemAnimationEvent(Connection connection, PacketCollectItem pkg) {
|
public CollectItemAnimationEvent(Connection connection, PacketCollectItem pkg) {
|
||||||
super(connection);
|
super(connection);
|
||||||
this.item = (ItemEntity) connection.getPlayer().getWorld().getEntity(pkg.getItemEntityId());
|
this.item = connection.getPlayer().getWorld().getEntity(pkg.getItemEntityId());
|
||||||
this.collector = connection.getPlayer().getWorld().getEntity(pkg.getCollectorEntityId());
|
this.collector = connection.getPlayer().getWorld().getEntity(pkg.getCollectorEntityId());
|
||||||
this.count = pkg.getCount();
|
this.count = pkg.getCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ItemEntity getItem() {
|
public Entity getItem() {
|
||||||
return this.item;
|
return this.item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,4 +33,25 @@ object MMath {
|
|||||||
}
|
}
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun divideUp(value: Int, divider: Int): Int {
|
||||||
|
return (value + divider - 1) / divider
|
||||||
|
}
|
||||||
|
|
||||||
|
fun divideUp(value: Float, divider: Float): Float {
|
||||||
|
return (value + divider - 1.0f) / divider
|
||||||
|
}
|
||||||
|
|
||||||
|
fun round10(value: Float): Int {
|
||||||
|
return ((value * 10).toInt() + 5) / 10
|
||||||
|
}
|
||||||
|
|
||||||
|
fun round10Up(value: Float): Int {
|
||||||
|
val intValue = value.toInt()
|
||||||
|
val rest = value / intValue
|
||||||
|
if (rest > 0) {
|
||||||
|
return intValue + 1
|
||||||
|
}
|
||||||
|
return intValue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user