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.atlas.HUDAtlasElement
|
||||
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.ProgressBar
|
||||
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.ExperienceChangeEvent
|
||||
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 glm_.vec2.Vec2
|
||||
|
||||
@ -40,6 +42,8 @@ class HotbarHUDElement(
|
||||
private lateinit var experienceBar: ProgressBar
|
||||
private lateinit var levelText: TextElement
|
||||
|
||||
private lateinit var healthBar: HealthBar
|
||||
|
||||
|
||||
override fun init() {
|
||||
hotbarBaseAtlasElement = hudRenderer.hudAtlasElements[ResourceLocation("minecraft:hotbar_base")]!!
|
||||
@ -55,6 +59,19 @@ class HotbarHUDElement(
|
||||
|
||||
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()
|
||||
|
||||
prepare()
|
||||
@ -83,6 +100,10 @@ class HotbarHUDElement(
|
||||
}
|
||||
prepare()
|
||||
})
|
||||
hudRenderer.connection.registerEvent(EventInvokerCallback<UpdateHealthEvent> {
|
||||
healthBar.value = it.health
|
||||
prepare()
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
@ -97,9 +118,15 @@ class HotbarHUDElement(
|
||||
|
||||
|
||||
if (hudRenderer.connection.player.gamemode != Gamemodes.CREATIVE) {
|
||||
healthBar.prepare()
|
||||
elementList.addChild(healthBar)
|
||||
|
||||
|
||||
if (hudRenderer.connection.player.level != 0) {
|
||||
// experience
|
||||
levelText.start = Vec2((hotbarBaseAtlasElement.binding.size.x - levelText.size.x) / 2, elementList.size.y)
|
||||
levelText.start = Vec2((hotbarBaseAtlasElement.binding.size.x - levelText.size.x) / 2, elementList.size.y - 3 * ELEMENT_PADDING)
|
||||
elementList.addChild(levelText)
|
||||
}
|
||||
|
||||
// experience bar
|
||||
experienceBar.start.y = elementList.size.y - ELEMENT_PADDING
|
||||
|
@ -27,13 +27,17 @@ open class ElementListElement(
|
||||
|
||||
fun clear() {
|
||||
clearCache()
|
||||
synchronized(children) {
|
||||
children.clear()
|
||||
}
|
||||
recalculateSize()
|
||||
}
|
||||
|
||||
fun addChild(child: Element) {
|
||||
child.parent = this
|
||||
synchronized(children) {
|
||||
children.add(child)
|
||||
}
|
||||
cache.clear()
|
||||
recalculateSize()
|
||||
}
|
||||
@ -50,10 +54,12 @@ open class ElementListElement(
|
||||
|
||||
override fun clearCache() {
|
||||
cache.clear()
|
||||
synchronized(children) {
|
||||
for (child in children) {
|
||||
child.clearCache()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkSize(vec2: Vec2) {
|
||||
var changed = false
|
||||
@ -84,9 +90,12 @@ open class ElementListElement(
|
||||
override fun prepareCache(start: Vec2, scaleFactor: Float, matrix: Mat4, z: Int) {
|
||||
val normalStart = addToStart(start, this.start * scaleFactor)
|
||||
|
||||
|
||||
synchronized(children) {
|
||||
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
|
||||
get() = text.message
|
||||
set(value) {
|
||||
text = ChatComponent.valueOf(sText)
|
||||
text = ChatComponent.valueOf(value)
|
||||
}
|
||||
|
||||
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_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_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)
|
||||
|
||||
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
|
||||
*/
|
||||
public class ChangeGameStateEvent extends CancelableEvent {
|
||||
public class ChangeGameStateEvent extends ConnectionEvent {
|
||||
private final PacketChangeGameState.Reason reason;
|
||||
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;
|
||||
|
||||
public class CollectItemAnimationEvent extends CancelableEvent {
|
||||
private final ItemEntity item;
|
||||
private final Entity item;
|
||||
private final Entity collector;
|
||||
private final int count;
|
||||
|
||||
@ -35,12 +35,12 @@ public class CollectItemAnimationEvent extends CancelableEvent {
|
||||
|
||||
public CollectItemAnimationEvent(Connection connection, PacketCollectItem pkg) {
|
||||
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.count = pkg.getCount();
|
||||
}
|
||||
|
||||
public ItemEntity getItem() {
|
||||
public Entity getItem() {
|
||||
return this.item;
|
||||
}
|
||||
|
||||
|
@ -33,4 +33,25 @@ object MMath {
|
||||
}
|
||||
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