hud: bossbar rendering

This commit is contained in:
Bixilon 2021-10-30 20:26:52 +02:00
parent e9287bbb44
commit a03f63b874
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
14 changed files with 562 additions and 37 deletions

View File

@ -15,7 +15,7 @@ package de.bixilon.minosoft.data.bossbar
import de.bixilon.minosoft.data.text.ChatComponent
data class Bossbar(
class Bossbar(
var title: ChatComponent = ChatComponent.EMPTY,
var value: Float = 0.0f,
var color: BossbarColors = BossbarColors.PINK,

View File

@ -3,6 +3,7 @@ package de.bixilon.minosoft.gui.rendering.gui.elements
interface Pollable {
/**
* A generic function that gets called in a specific interval to check for changed data
* @return true, if any value changed
*/
fun poll(): Boolean

View File

@ -112,6 +112,19 @@ open class RowLayout(
forceApply() // ToDo: Optimize: Keep current layout, just add the element without redoing stuff
}
operator fun minusAssign(element: Element) = remove(element)
fun remove(element: Element) {
val index = children.indexOf(element)
if (index < 0) {
return
}
element.parent = null
children.removeAt(index)
forceApply() // ToDo: Optimize: Keep current layout, just add the element without redoing stuff
}
@Synchronized
override fun forceSilentApply() {
for (child in children) {

View File

@ -0,0 +1,68 @@
/*
* 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.elements.util
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.gui.rendering.gui.mesh.GUIVertexOptions
import de.bixilon.minosoft.gui.rendering.util.VecUtil
import glm_.vec2.Vec2
import glm_.vec2.Vec2i
open class ProgressElement(
hudRenderer: HUDRenderer,
val emptyAtlasElement: HUDAtlasElement,
val fullAtlasElement: HUDAtlasElement,
progress: Float = 0.0f,
) : Element(hudRenderer) {
var progress = progress
set(value) {
if (field == value) {
return
}
field = value
forceSilentApply()
// ToDo: Animate
}
protected val emptyImage = ImageElement(hudRenderer, emptyAtlasElement)
protected lateinit var progressImage: ImageElement
constructor(hudRenderer: HUDRenderer, atlasElements: Array<HUDAtlasElement>, progress: Float = 0.0f) : this(hudRenderer, atlasElements[0], atlasElements[1], progress)
init {
_size = emptyAtlasElement.size
forceSilentApply()
}
override fun forceRender(offset: Vec2i, z: Int, consumer: GUIVertexConsumer, options: GUIVertexOptions?): Int {
emptyImage.render(offset, z, consumer, options)
progressImage.render(offset, z + 1, consumer, options)
return LAYERS
}
override fun forceSilentApply() {
progressImage = ImageElement(hudRenderer, fullAtlasElement.texture, uvStart = fullAtlasElement.uvStart, uvEnd = Vec2(VecUtil.lerp(progress, fullAtlasElement.uvStart.x, fullAtlasElement.uvEnd.x), fullAtlasElement.uvEnd.y), size = Vec2i((fullAtlasElement.size.x * progress).toInt(), emptyAtlasElement.size.y))
cacheUpToDate = false
}
companion object {
const val LAYERS = 2 // background, foreground
}
}

View File

@ -26,6 +26,7 @@ import de.bixilon.minosoft.gui.rendering.gui.elements.Pollable
import de.bixilon.minosoft.gui.rendering.gui.hud.atlas.HUDAtlasManager
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.HUDBuilder
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.LayoutedHUDElement
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.bossbar.BossbarHUDElement
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.chat.ChatHUDElement
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.chat.InternalMessagesHUDElement
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.hotbar.HotbarHUDElement
@ -85,14 +86,15 @@ class HUDRenderer(
if (Minosoft.config.config.game.hud.crosshair.enabled) {
registerElement(CrosshairHUDElement)
}
registerElement(BossbarHUDElement)
if (Minosoft.config.config.game.hud.chat.enabled) {
registerElement(ChatHUDElement)
}
if (Minosoft.config.config.game.hud.internalMessages.enabled) {
registerElement(InternalMessagesHUDElement)
}
registerElement(TabListHUDElement)
registerElement(BreakProgressHUDElement)
registerElement(TabListHUDElement)
registerElement(HotbarHUDElement)
registerElement(WorldInfoHUDElement)
registerElement(TitleHUDElement)

View File

@ -0,0 +1,116 @@
/*
* 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.bossbar
import de.bixilon.minosoft.data.bossbar.Bossbar
import de.bixilon.minosoft.data.bossbar.BossbarColors
import de.bixilon.minosoft.data.bossbar.BossbarNotches
import de.bixilon.minosoft.gui.rendering.gui.elements.Element
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.Pollable
import de.bixilon.minosoft.gui.rendering.gui.elements.text.TextElement
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.gui.rendering.gui.mesh.GUIVertexOptions
import de.bixilon.minosoft.util.KUtil.unsafeCast
import glm_.vec2.Vec2i
import java.lang.Integer.max
class BossbarElement(
hudRenderer: HUDRenderer,
val bossbar: Bossbar,
val atlas: Array<Array<Array<HUDAtlasElement?>>>,
) : Element(hudRenderer), Pollable {
private var color: BossbarColors = bossbar.color
private var notches: BossbarNotches = bossbar.notches
private val titleElement = TextElement(hudRenderer, text = bossbar.title, background = false, parent = this)
private lateinit var progress: BossbarProgressElement
init {
forceSilentApply()
setStyle()
}
override fun forceRender(offset: Vec2i, z: Int, consumer: GUIVertexConsumer, options: GUIVertexOptions?): Int {
val titleSize = titleElement.size
titleElement.render(offset + Vec2i(HorizontalAlignments.CENTER.getOffset(size.x, titleSize.x), 0), z, consumer, options)
progress.render(offset + Vec2i(0, titleSize.y), z, consumer, options)
return TextElement.LAYERS
}
override fun poll(): Boolean {
var changes = 0
val title = bossbar.title
if (titleElement.chatComponent != title) {
titleElement.text = title
changes++
}
val changesBeforeStyle = changes
val color = bossbar.color
if (this.color != color) {
this.color = color
changes++
}
val notches = bossbar.notches
if (this.notches != notches) {
this.notches = notches
changes++
}
if (changes < changesBeforeStyle) {
setStyle()
}
val value = bossbar.value
if (progress.progress != value) {
progress.progress = value
changes++
}
return changes > 0
}
private fun setStyle() {
// ToDo: Cache progress
val notches = if (notches == BossbarNotches.NO_NOTCHES) {
null
} else {
atlas[1][notches.ordinal - 1]
}
progress = BossbarProgressElement(hudRenderer, atlas[0][color.ordinal].unsafeCast(), notches.unsafeCast(), 0.0f)
}
override fun forceSilentApply() {
val size = Vec2i(BAR_SIZE)
size.x = max(size.x, titleElement.size.x)
size.y += titleElement.size.y
_size = size
cacheUpToDate = false
}
override fun onChildChange(child: Element) {}
companion object {
private val BAR_SIZE = Vec2i(182, 5)
}
}

View File

@ -0,0 +1,125 @@
/*
* 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.bossbar
import de.bixilon.minosoft.data.bossbar.Bossbar
import de.bixilon.minosoft.data.registries.ResourceLocation
import de.bixilon.minosoft.gui.rendering.gui.elements.HorizontalAlignments
import de.bixilon.minosoft.gui.rendering.gui.elements.layout.RowLayout
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.LayoutedHUDElement
import de.bixilon.minosoft.modding.event.events.bossbar.*
import de.bixilon.minosoft.modding.event.invoker.CallbackEventInvoker
import de.bixilon.minosoft.util.KUtil.synchronizedMapOf
import de.bixilon.minosoft.util.KUtil.toResourceLocation
import glm_.vec2.Vec2i
class BossbarHUDElement(hudRenderer: HUDRenderer) : LayoutedHUDElement<RowLayout>(hudRenderer) {
private val connection = renderWindow.connection
override val layout: RowLayout = RowLayout(hudRenderer, HorizontalAlignments.CENTER, 2)
private val bossbars: MutableMap<Bossbar, BossbarElement> = synchronizedMapOf()
override val layoutOffset: Vec2i
get() = Vec2i((hudRenderer.scaledSize.x - layout.size.x) / 2, 2)
val atlasManager = hudRenderer.atlasManager
/**
* [bar|notches][color.ordinal|notches.ordinal-1][empty|full]
*/
private val atlas = arrayOf(
arrayOf(
arrayOf(
atlasManager["minecraft:bossbar_pink_empty"],
atlasManager["minecraft:bossbar_pink_full"],
),
arrayOf(
atlasManager["minecraft:bossbar_blue_empty"],
atlasManager["minecraft:bossbar_blue_full"],
),
arrayOf(
atlasManager["minecraft:bossbar_red_empty"],
atlasManager["minecraft:bossbar_red_full"],
),
arrayOf(
atlasManager["minecraft:bossbar_green_empty"],
atlasManager["minecraft:bossbar_green_full"],
),
arrayOf(
atlasManager["minecraft:bossbar_yellow_empty"],
atlasManager["minecraft:bossbar_yellow_full"],
),
arrayOf(
atlasManager["minecraft:bossbar_purple_empty"],
atlasManager["minecraft:bossbar_purple_full"],
),
arrayOf(
atlasManager["minecraft:bossbar_white_empty"],
atlasManager["minecraft:bossbar_white_full"],
),
),
arrayOf(
arrayOf(
atlasManager["minecraft:bossbar_notches_6_empty"],
atlasManager["minecraft:bossbar_notches_6_full"],
),
arrayOf(
atlasManager["minecraft:bossbar_notches_10_empty"],
atlasManager["minecraft:bossbar_notches_10_full"],
),
arrayOf(
atlasManager["minecraft:bossbar_notches_12_empty"],
atlasManager["minecraft:bossbar_notches_12_empty"],
),
arrayOf(
atlasManager["minecraft:bossbar_notches_20_empty"],
atlasManager["minecraft:bossbar_notches_20_full"],
),
),
)
override fun postInit() {
connection.registerEvent(CallbackEventInvoker.of<BossbarAddEvent> {
val element = BossbarElement(hudRenderer, it.bossbar, atlas)
layout += element
val previous = bossbars.put(it.bossbar, element) ?: return@of
layout -= previous
})
connection.registerEvent(CallbackEventInvoker.of<BossbarRemoveEvent> {
val element = bossbars.remove(it.bossbar) ?: return@of
layout -= element
})
connection.registerEvent(CallbackEventInvoker.of<BossbarValueSetEvent> {
bossbars[it.bossbar]?.apply()
})
connection.registerEvent(CallbackEventInvoker.of<BossbarTitleSetEvent> {
bossbars[it.bossbar]?.apply()
})
connection.registerEvent(CallbackEventInvoker.of<BossbarStyleSetEvent> {
bossbars[it.bossbar]?.apply()
})
}
companion object : HUDBuilder<BossbarHUDElement> {
override val RESOURCE_LOCATION: ResourceLocation = "minosoft:bossbar".toResourceLocation()
override fun build(hudRenderer: HUDRenderer): BossbarHUDElement {
return BossbarHUDElement(hudRenderer)
}
}
}

View File

@ -0,0 +1,49 @@
/*
* 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.bossbar
import de.bixilon.minosoft.gui.rendering.gui.elements.primitive.ImageElement
import de.bixilon.minosoft.gui.rendering.gui.elements.util.ProgressElement
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.gui.rendering.gui.mesh.GUIVertexOptions
import glm_.vec2.Vec2i
open class BossbarProgressElement(
hudRenderer: HUDRenderer,
emptyProgressAtlasElement: HUDAtlasElement,
fullProgressAtlasElement: HUDAtlasElement,
emptyNotchesElement: HUDAtlasElement?,
fullNotchesElement: HUDAtlasElement?,
progress: Float = 0.0f,
) : ProgressElement(hudRenderer, emptyProgressAtlasElement, fullProgressAtlasElement, progress) {
private val emptyNotchesImage = emptyNotchesElement?.let { ImageElement(hudRenderer, it, emptyProgressAtlasElement.size) }
private val fullNotchesImage = fullNotchesElement?.let { ImageElement(hudRenderer, it, emptyProgressAtlasElement.size) }
constructor(hudRenderer: HUDRenderer, progressElements: Array<HUDAtlasElement>, notchesElements: Array<HUDAtlasElement>?, progress: Float = 0.0f) : this(hudRenderer, progressElements[0], progressElements[1], notchesElements?.get(0), notchesElements?.get(1), progress)
override fun forceRender(offset: Vec2i, z: Int, consumer: GUIVertexConsumer, options: GUIVertexOptions?): Int {
emptyImage.render(offset, z, consumer, options)
emptyNotchesImage?.render(offset, z + 1, consumer, options)
progressImage.render(offset, z + 2, consumer, options)
fullNotchesImage?.render(offset, z + 3, consumer, options)
return LAYERS
}
companion object {
const val LAYERS = 4 // background, foreground * 2 (notches)
}
}

View File

@ -20,13 +20,11 @@ import de.bixilon.minosoft.gui.rendering.gui.elements.Element
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.Pollable
import de.bixilon.minosoft.gui.rendering.gui.elements.primitive.ImageElement
import de.bixilon.minosoft.gui.rendering.gui.elements.text.TextElement
import de.bixilon.minosoft.gui.rendering.gui.elements.util.ProgressElement
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.GUIVertexOptions
import de.bixilon.minosoft.gui.rendering.util.VecUtil.lerp
import glm_.vec2.Vec2
import glm_.vec2.Vec2i
class HotbarExperienceBarElement(hudRenderer: HUDRenderer) : Element(hudRenderer), Pollable {
@ -58,15 +56,8 @@ class HotbarExperienceBarElement(hudRenderer: HUDRenderer) : Element(hudRenderer
override fun forceRender(offset: Vec2i, z: Int, consumer: GUIVertexConsumer, options: GUIVertexOptions?): Int {
val bars = atlasElements[barIndex]
// background
ImageElement(hudRenderer, bars[0]).render(offset, z, consumer, options)
val progressAtlasElement = bars[1]
// foreground
val progress = ImageElement(hudRenderer, progressAtlasElement.texture, uvStart = progressAtlasElement.uvStart, uvEnd = Vec2(lerp(progress, progressAtlasElement.uvStart.x, progressAtlasElement.uvEnd.x), progressAtlasElement.uvEnd.y), size = Vec2i((progressAtlasElement.size.x * progress).toInt(), SIZE.y))
progress.render(offset, z + 1, consumer, options)
val progress = ProgressElement(hudRenderer, bars, progress)
progress.render(offset, z, consumer, options)
if (level > 0) {
// level
@ -75,7 +66,7 @@ class HotbarExperienceBarElement(hudRenderer: HUDRenderer) : Element(hudRenderer
text.render(offset + Vec2i(HorizontalAlignments.CENTER.getOffset(size.x, text.size.x), -Font.CHAR_HEIGHT + 1), z + 2, consumer, options)
}
return 2 + TextElement.LAYERS // background + foreground + text(level)
return ProgressElement.LAYERS + TextElement.LAYERS // background + foreground + text(level)
}
override fun forceSilentApply() {

View File

@ -35,12 +35,8 @@ class HotbarHUDElement(hudRenderer: HUDRenderer) : LayoutedHUDElement<HotbarElem
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 = HotbarElement(hudRenderer) // ToDo: The base uses image elements, that are available after init stage
layout.prefMaxSize = Vec2i(-1, -1)
connection.registerEvent(CallbackEventInvoker.of<ExperienceChangeEvent> {

View File

@ -57,9 +57,7 @@ class BlockPlaceC2SP(
buffer.writeByte((cursorPosition.y * 15.0f).toInt())
buffer.writeByte((cursorPosition.z * 15.0f).toInt())
} else {
buffer.writeFloat(cursorPosition.x)
buffer.writeFloat(cursorPosition.y)
buffer.writeFloat(cursorPosition.z)
buffer.writeVec3f(cursorPosition)
}
if (buffer.versionId >= ProtocolVersions.V_19W03A) {
@ -68,6 +66,6 @@ class BlockPlaceC2SP(
}
override fun log() {
Log.log(LogMessageType.NETWORK_PACKETS_OUT, LogLevels.VERBOSE) { "Place block (position=$position, direction=$direction, item=$item, cursor=$cursorPosition, hand=$hand, insideBlock=$insideBlock)" }
Log.log(LogMessageType.NETWORK_PACKETS_OUT, LogLevels.VERBOSE) { "Place block (position=$position, direction=$direction, cursor=$cursorPosition, hand=$hand, insideBlock=$insideBlock)" }
}
}

View File

@ -37,9 +37,7 @@ class EntityInteractAtC2SP(
if (buffer.versionId >= ProtocolVersions.V_14W32A) {
// position
buffer.writeFloat(this.position.x)
buffer.writeFloat(this.position.y)
buffer.writeFloat(this.position.z)
buffer.writeVec3f(position)
if (buffer.versionId >= ProtocolVersions.V_15W31A) {
buffer.writeVarInt(hand.ordinal)

View File

@ -22,17 +22,17 @@ object BossbarS2CPF {
fun createPacket(buffer: PlayInByteBuffer): PlayS2CPacket {
val uuid = buffer.readUUID()
return when (BossBarActions[buffer.readVarInt()]) {
BossBarActions.ADD -> BossbarAddS2CP(uuid, buffer)
BossBarActions.REMOVE -> BossbarRemoveS2CP(uuid)
BossBarActions.SET_VALUE -> BossbarValueSetS2CP(uuid, buffer)
BossBarActions.SET_TITLE -> BossbarTitleSetS2CP(uuid, buffer)
BossBarActions.SET_STYLE -> BossbarStyleSetS2CP(uuid, buffer)
BossBarActions.SET_FLAGS -> BossbarFlagSetS2CP(uuid, buffer)
return when (BossbarActions[buffer.readVarInt()]) {
BossbarActions.ADD -> BossbarAddS2CP(uuid, buffer)
BossbarActions.REMOVE -> BossbarRemoveS2CP(uuid)
BossbarActions.SET_VALUE -> BossbarValueSetS2CP(uuid, buffer)
BossbarActions.SET_TITLE -> BossbarTitleSetS2CP(uuid, buffer)
BossbarActions.SET_STYLE -> BossbarStyleSetS2CP(uuid, buffer)
BossbarActions.SET_FLAGS -> BossbarFlagSetS2CP(uuid, buffer)
}
}
enum class BossBarActions {
enum class BossbarActions {
ADD,
REMOVE,
SET_VALUE,
@ -41,9 +41,9 @@ object BossbarS2CPF {
SET_FLAGS,
;
companion object : ValuesEnum<BossBarActions> {
companion object : ValuesEnum<BossbarActions> {
override val VALUES = values()
override val NAME_MAP: Map<String, BossBarActions> = KUtil.getEnumValues(VALUES)
override val NAME_MAP: Map<String, BossbarActions> = KUtil.getEnumValues(VALUES)
}
}
}

View File

@ -491,5 +491,173 @@
"start": [88, 9],
"end": [97, 18]
}
},
"minecraft:wither_bar_empty": {
"0": {
"texture": "minecraft:textures/gui/icons.png",
"start": [0, 74],
"end": [182, 79]
}
},
"minecraft:wither_bar_full": {
"0": {
"texture": "minecraft:textures/gui/icons.png",
"start": [0, 79],
"end": [182, 84]
}
},
"minecraft:bossbar_pink_empty": {
"0": {
"texture": "minecraft:textures/gui/bars.png",
"start": [0, 0],
"end": [182, 5]
}
},
"minecraft:bossbar_pink_full": {
"0": {
"texture": "minecraft:textures/gui/bars.png",
"start": [0, 5],
"end": [182, 10]
}
},
"minecraft:bossbar_blue_empty": {
"0": {
"texture": "minecraft:textures/gui/bars.png",
"start": [0, 10],
"end": [182, 15]
}
},
"minecraft:bossbar_blue_full": {
"0": {
"texture": "minecraft:textures/gui/bars.png",
"start": [0, 15],
"end": [182, 20]
}
},
"minecraft:bossbar_red_empty": {
"0": {
"texture": "minecraft:textures/gui/bars.png",
"start": [0, 20],
"end": [182, 25]
}
},
"minecraft:bossbar_red_full": {
"0": {
"texture": "minecraft:textures/gui/bars.png",
"start": [0, 25],
"end": [182, 30]
}
},
"minecraft:bossbar_green_empty": {
"0": {
"texture": "minecraft:textures/gui/bars.png",
"start": [0, 30],
"end": [182, 35]
}
},
"minecraft:bossbar_green_full": {
"0": {
"texture": "minecraft:textures/gui/bars.png",
"start": [0, 35],
"end": [182, 40]
}
},
"minecraft:bossbar_yellow_empty": {
"0": {
"texture": "minecraft:textures/gui/bars.png",
"start": [0, 40],
"end": [182, 45]
}
},
"minecraft:bossbar_yellow_full": {
"0": {
"texture": "minecraft:textures/gui/bars.png",
"start": [0, 45],
"end": [182, 50]
}
},
"minecraft:bossbar_purple_empty": {
"0": {
"texture": "minecraft:textures/gui/bars.png",
"start": [0, 50],
"end": [182, 55]
}
},
"minecraft:bossbar_purple_full": {
"0": {
"texture": "minecraft:textures/gui/bars.png",
"start": [0, 55],
"end": [182, 60]
}
},
"minecraft:bossbar_white_empty": {
"0": {
"texture": "minecraft:textures/gui/bars.png",
"start": [0, 60],
"end": [182, 65]
}
},
"minecraft:bossbar_white_full": {
"0": {
"texture": "minecraft:textures/gui/bars.png",
"start": [0, 65],
"end": [182, 70]
}
},
"minecraft:bossbar_notches_6_empty": {
"0": {
"texture": "minecraft:textures/gui/bars.png",
"start": [0, 80],
"end": [182, 85]
}
},
"minecraft:bossbar_notches_6_full": {
"0": {
"texture": "minecraft:textures/gui/bars.png",
"start": [0, 85],
"end": [182, 90]
}
},
"minecraft:bossbar_notches_10_empty": {
"0": {
"texture": "minecraft:textures/gui/bars.png",
"start": [0, 90],
"end": [182, 95]
}
},
"minecraft:bossbar_notches_10_full": {
"0": {
"texture": "minecraft:textures/gui/bars.png",
"start": [0, 95],
"end": [182, 100]
}
},
"minecraft:bossbar_notches_12_empty": {
"0": {
"texture": "minecraft:textures/gui/bars.png",
"start": [0, 100],
"end": [182, 105]
}
},
"minecraft:bossbar_notches_12_full": {
"0": {
"texture": "minecraft:textures/gui/bars.png",
"start": [0, 105],
"end": [182, 110]
}
},
"minecraft:bossbar_notches_20_empty": {
"0": {
"texture": "minecraft:textures/gui/bars.png",
"start": [0, 110],
"end": [182, 115]
}
},
"minecraft:bossbar_notches_20_full": {
"0": {
"texture": "minecraft:textures/gui/bars.png",
"start": [0, 115],
"end": [182, 120]
}
}
}