rendering: crosshair, improved hotbar, experience bar, network: add packet data check

This commit is contained in:
Bixilon 2021-03-04 20:38:51 +01:00
parent 71a75b7b53
commit 63eb03a17b
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
17 changed files with 286 additions and 122 deletions

View File

@ -39,6 +39,7 @@ class Player(val account: Account) {
var selectedSlot: Int = 0 var selectedSlot: Int = 0
var level = 0 var level = 0
var totalExperience = 0 var totalExperience = 0
var experienceBarProgress = 0f
var entity: PlayerEntity? = null var entity: PlayerEntity? = null
var isSpawnConfirmed = false var isSpawnConfirmed = false
var playerUUID: UUID = account.uuid var playerUUID: UUID = account.uuid

View File

@ -13,6 +13,7 @@
package de.bixilon.minosoft.gui.rendering.hud package de.bixilon.minosoft.gui.rendering.hud
import de.bixilon.minosoft.data.text.RGBColor
import de.bixilon.minosoft.gui.rendering.util.Mesh import de.bixilon.minosoft.gui.rendering.util.Mesh
import glm_.BYTES import glm_.BYTES
import glm_.vec2.Vec2 import glm_.vec2.Vec2
@ -32,21 +33,28 @@ class HUDMesh : Mesh() {
glEnableVertexAttribArray(index++) glEnableVertexAttribArray(index++)
glVertexAttribPointer(index, 1, GL_FLOAT, false, FLOATS_PER_VERTEX * Float.BYTES, (5 * Float.BYTES).toLong()) glVertexAttribPointer(index, 1, GL_FLOAT, false, FLOATS_PER_VERTEX * Float.BYTES, (5 * Float.BYTES).toLong())
glEnableVertexAttribArray(index++) glEnableVertexAttribArray(index++)
glVertexAttribPointer(index, 1, GL_FLOAT, false, FLOATS_PER_VERTEX * Float.BYTES, (6 * Float.BYTES).toLong())
glEnableVertexAttribArray(index++)
super.unbind() super.unbind()
} }
fun addVertex(position: Vec3, textureCoordinates: Vec2, atlasPage: Int) { fun addVertex(position: Vec3, textureCoordinates: Vec2, atlasPage: Int, tintColor: RGBColor? = null) {
data.add(position.x) data.add(position.x)
data.add(position.y) data.add(position.y)
data.add(position.z) data.add(position.z)
data.add(textureCoordinates.x) data.add(textureCoordinates.x)
data.add(textureCoordinates.y) data.add(textureCoordinates.y)
data.add(Float.fromBits(atlasPage)) data.add(Float.fromBits(atlasPage))
if (tintColor == null) {
data.add(0f)
} else {
data.add(Float.fromBits(tintColor.color))
}
} }
companion object { companion object {
private const val FLOATS_PER_VERTEX = 6 private const val FLOATS_PER_VERTEX = 7
} }
} }

View File

@ -19,6 +19,7 @@ import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.Renderer import de.bixilon.minosoft.gui.rendering.Renderer
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.other.CrosshairHUDElement
import de.bixilon.minosoft.gui.rendering.hud.elements.other.HotbarHUDElement import de.bixilon.minosoft.gui.rendering.hud.elements.other.HotbarHUDElement
import de.bixilon.minosoft.gui.rendering.hud.elements.text.HUDTextElement import de.bixilon.minosoft.gui.rendering.hud.elements.text.HUDTextElement
import de.bixilon.minosoft.gui.rendering.shader.Shader import de.bixilon.minosoft.gui.rendering.shader.Shader
@ -37,10 +38,11 @@ class HUDRenderer(val connection: Connection, val renderWindow: RenderWindow) :
val hudElements: MutableMap<ResourceLocation, HUDElement> = mutableMapOf( val hudElements: MutableMap<ResourceLocation, HUDElement> = mutableMapOf(
ResourceLocation("minosoft:hud_text_renderer") to HUDTextElement(connection, this, renderWindow), ResourceLocation("minosoft:hud_text_renderer") to HUDTextElement(connection, this, renderWindow),
ResourceLocation("minosoft:hotbar") to HotbarHUDElement(this), ResourceLocation("minosoft:hotbar") to HotbarHUDElement(this),
ResourceLocation("minosoft:crosshair") to CrosshairHUDElement(this),
) )
val hudShader = Shader(ResourceLocation(ProtocolDefinition.MINOSOFT_NAMESPACE, "rendering/shader/hud_vertex.glsl"), ResourceLocation(ProtocolDefinition.MINOSOFT_NAMESPACE, "rendering/shader/hud_fragment.glsl")) val hudShader = Shader(ResourceLocation(ProtocolDefinition.MINOSOFT_NAMESPACE, "rendering/shader/hud_vertex.glsl"), ResourceLocation(ProtocolDefinition.MINOSOFT_NAMESPACE, "rendering/shader/hud_fragment.glsl"))
lateinit var hudTextures: TextureArray lateinit var hudAtlasTextures: TextureArray
lateinit var hudImages: Map<ResourceLocation, HUDAtlasElement> lateinit var hudAtlasElements: Map<ResourceLocation, HUDAtlasElement>
var lastTickTime = 0L var lastTickTime = 0L
var orthographicMatrix: Mat4 = Mat4() var orthographicMatrix: Mat4 = Mat4()
private set private set
@ -51,10 +53,10 @@ class HUDRenderer(val connection: Connection, val renderWindow: RenderWindow) :
hudShader.load(Minosoft.MINOSOFT_ASSETS_MANAGER) hudShader.load(Minosoft.MINOSOFT_ASSETS_MANAGER)
val hudImages = HUDAtlasElement.deserialize(ResourceLocationJsonMap.create(Minosoft.MINOSOFT_ASSETS_MANAGER.readJsonAsset(ResourceLocation(ProtocolDefinition.MINOSOFT_NAMESPACE, "mapping/atlas.json"))), connection.version.versionId) val hudImages = HUDAtlasElement.deserialize(ResourceLocationJsonMap.create(Minosoft.MINOSOFT_ASSETS_MANAGER.readJsonAsset(ResourceLocation(ProtocolDefinition.MINOSOFT_NAMESPACE, "mapping/atlas.json"))), connection.version.versionId)
this.hudImages = hudImages.second this.hudAtlasElements = hudImages.second
hudTextures = TextureArray.createTextureArray(connection.version.assetsManager, hudImages.first.toSet()) hudAtlasTextures = TextureArray.createTextureArray(connection.version.assetsManager, hudImages.first.toSet())
hudTextures.load() hudAtlasTextures.load()
for (element in hudElements.values) { for (element in hudElements.values) {
element.init() element.init()
@ -62,7 +64,7 @@ class HUDRenderer(val connection: Connection, val renderWindow: RenderWindow) :
} }
override fun postInit() { override fun postInit() {
hudTextures.use(hudShader, "hudTextureArray") hudAtlasTextures.use(hudShader, "hudTextureArray")
for (element in hudElements.values) { for (element in hudElements.values) {
element.postInit() element.postInit()
} }

View File

@ -22,14 +22,14 @@ data class Vec2Binding(
val start: Vec2, val start: Vec2,
val end: Vec2, val end: Vec2,
) { ) {
val size: Vec2 = glm.abs(Vec2(start - end)) val size: Vec2 = glm.abs(Vec2(start - end)) + 1
companion object { companion object {
fun deserialize(json: JsonElement): Vec2Binding { fun deserialize(json: JsonElement): Vec2Binding {
check(json is JsonObject) check(json is JsonObject)
return Vec2Binding(json["start"].asJsonArray.let { Vec2(it[0].asInt, it[1].asInt) }, json["end"].asJsonArray.let { Vec2(it[0].asInt, it[1].asInt) + 1 }) return Vec2Binding(json["start"].asJsonArray.let { Vec2(it[0].asInt, it[1].asInt) }, json["end"].asJsonArray.let { Vec2(it[0].asInt, it[1].asInt) })
} }
} }
} }

View File

@ -17,7 +17,6 @@ import de.bixilon.minosoft.gui.rendering.hud.HUDElementProperties
import de.bixilon.minosoft.gui.rendering.hud.HUDMesh import de.bixilon.minosoft.gui.rendering.hud.HUDMesh
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.other.HotbarHUDElement
import glm_.vec2.Vec2 import glm_.vec2.Vec2
import glm_.vec3.Vec3 import glm_.vec3.Vec3
import glm_.vec4.Vec4 import glm_.vec4.Vec4
@ -33,13 +32,13 @@ abstract class HUDElement(protected val hudRenderer: HUDRenderer) {
open fun screenChangeResizeCallback(screenWidth: Int, screenHeight: Int) {} open fun screenChangeResizeCallback(screenWidth: Int, screenHeight: Int) {}
fun getRealPosition(elementSize: Vec2, elementProperties: HUDElementProperties, realType: HotbarHUDElement.RealTypes, innerOffset: Vec2 = Vec2()): Vec2 { fun getRealPosition(elementSize: Vec2, elementProperties: HUDElementProperties, realType: RealTypes, innerOffset: Vec2 = Vec2()): Vec2 {
// ToDo: Improve this code // ToDo: Improve this code
val halfElementSize = elementSize / 2f val halfElementSize = elementSize / 2f
val realPosition = elementProperties.position * hudRenderer.renderWindow.screenDimensions val realPosition = elementProperties.position * hudRenderer.renderWindow.screenDimensions
fun getValue(elementSize: Float, halfSize: Float, position: Float, binding: HUDElementProperties.PositionBindings, innerOffset: Float): Float { fun getValue(elementSize: Float, halfSize: Float, position: Float, binding: HUDElementProperties.PositionBindings, innerOffset: Float): Float {
val ourHalfSize = if (realType == HotbarHUDElement.RealTypes.START) { val ourHalfSize = if (realType == RealTypes.START) {
-halfSize -halfSize
} else { } else {
halfSize halfSize
@ -63,14 +62,14 @@ abstract class HUDElement(protected val hudRenderer: HUDRenderer) {
0f 0f
} else { } else {
when (realType) { when (realType) {
HotbarHUDElement.RealTypes.START -> { RealTypes.START -> {
if (position < 0f) { if (position < 0f) {
position position
} else { } else {
position - (elementSize) position - (elementSize)
} }
} }
HotbarHUDElement.RealTypes.END -> { RealTypes.END -> {
if (position < 0f) { if (position < 0f) {
position + (elementSize) position + (elementSize)
} else { } else {
@ -91,15 +90,20 @@ abstract class HUDElement(protected val hudRenderer: HUDRenderer) {
fun drawImage(start: Vec2, end: Vec2, hudMesh: HUDMesh, hudAtlasElement: HUDAtlasElement, z: Int = 1) { fun drawImage(start: Vec2, end: Vec2, hudMesh: HUDMesh, hudAtlasElement: HUDAtlasElement, z: Int = 1) {
val textureStart = Vec2((hudAtlasElement.binding.start.x * hudAtlasElement.texture.widthFactor) / hudAtlasElement.texture.width.toFloat(), (hudAtlasElement.binding.start.y * hudAtlasElement.texture.heightFactor) / hudAtlasElement.texture.height.toFloat())
val textureEnd = Vec2(((hudAtlasElement.binding.end.x + 1) * hudAtlasElement.texture.widthFactor) / (hudAtlasElement.texture.width + 1f), ((hudAtlasElement.binding.end.y + 1) * hudAtlasElement.texture.heightFactor) / (hudAtlasElement.texture.height + 1f))
drawImage(start, end, hudMesh, hudAtlasElement, textureStart, textureEnd, z)
}
fun drawImage(start: Vec2, end: Vec2, hudMesh: HUDMesh, hudAtlasElement: HUDAtlasElement, textureStart: Vec2, textureEnd: Vec2, z: Int = 1) {
val modelStart = hudRenderer.orthographicMatrix * Vec4(start, 1f, 1.0f) val modelStart = hudRenderer.orthographicMatrix * Vec4(start, 1f, 1.0f)
val modelEnd = hudRenderer.orthographicMatrix * Vec4(end, 1f, 1.0f) val modelEnd = hudRenderer.orthographicMatrix * Vec4(end, 1f, 1.0f)
val textureStart = Vec2((hudAtlasElement.binding.start.x * hudAtlasElement.texture.widthFactor) / hudAtlasElement.texture.width.toFloat(), (hudAtlasElement.binding.start.y * hudAtlasElement.texture.heightFactor) / hudAtlasElement.texture.height.toFloat())
val textureEnd = Vec2((hudAtlasElement.binding.end.x * hudAtlasElement.texture.widthFactor) / hudAtlasElement.texture.width.toFloat(), (hudAtlasElement.binding.end.y * hudAtlasElement.texture.heightFactor) / hudAtlasElement.texture.height.toFloat())
val realZ = HUD_Z_COORDINATE + HUD_Z_COORDINATE_Z_FACTOR * z val realZ = HUD_Z_COORDINATE + HUD_Z_COORDINATE_Z_FACTOR * z
hudMesh.addVertex(Vec3(modelStart.x, modelStart.y, realZ), Vec2(textureStart.x, textureEnd.y), hudAtlasElement.texture.id) hudMesh.addVertex(Vec3(modelStart.x, modelStart.y, realZ), Vec2(textureStart.x, textureEnd.y), hudAtlasElement.texture.id)
hudMesh.addVertex(Vec3(modelEnd.x, modelStart.y, realZ), Vec2(textureEnd.x, textureEnd.y), hudAtlasElement.texture.id) hudMesh.addVertex(Vec3(modelEnd.x, modelStart.y, realZ), Vec2(textureEnd.x, textureEnd.y), hudAtlasElement.texture.id)
hudMesh.addVertex(Vec3(modelStart.x, modelEnd.y, realZ), Vec2(textureStart.x, textureStart.y), hudAtlasElement.texture.id) hudMesh.addVertex(Vec3(modelStart.x, modelEnd.y, realZ), Vec2(textureStart.x, textureStart.y), hudAtlasElement.texture.id)
@ -108,6 +112,12 @@ abstract class HUDElement(protected val hudRenderer: HUDRenderer) {
hudMesh.addVertex(Vec3(modelEnd.x, modelEnd.y, realZ), Vec2(textureEnd.x, textureStart.y), hudAtlasElement.texture.id) hudMesh.addVertex(Vec3(modelEnd.x, modelEnd.y, realZ), Vec2(textureEnd.x, textureStart.y), hudAtlasElement.texture.id)
} }
enum class RealTypes {
START,
END
}
companion object { companion object {
private const val HUD_Z_COORDINATE = -0.9996f private const val HUD_Z_COORDINATE = -0.9996f
private const val HUD_Z_COORDINATE_Z_FACTOR = -0.000001f private const val HUD_Z_COORDINATE_Z_FACTOR = -0.000001f

View File

@ -0,0 +1,46 @@
/*
* 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
import de.bixilon.minosoft.gui.rendering.hud.HUDMesh
import de.bixilon.minosoft.gui.rendering.hud.atlas.HUDAtlasElement
import glm_.vec2.Vec2
import kotlin.math.abs
class ProgressBar(
private val emptyAtlasElement: HUDAtlasElement,
private val fullAtlasElement: HUDAtlasElement,
private val hudElement: HUDElement,
) {
val size: Vec2 = emptyAtlasElement.binding.size
fun draw(hudMesh: HUDMesh, start: Vec2, end: Vec2, progress: Float, z: Int = 1) {
hudElement.drawImage(start, end, hudMesh, emptyAtlasElement, z)
if (progress == 0.0f) {
return
}
val xDiff = abs(end.x - start.x)
val ourXDiff = xDiff * progress
val textureStart = Vec2((fullAtlasElement.binding.start.x * fullAtlasElement.texture.widthFactor) / fullAtlasElement.texture.width.toFloat(), (fullAtlasElement.binding.start.y * fullAtlasElement.texture.heightFactor) / fullAtlasElement.texture.height.toFloat())
var textureEnd = Vec2(((fullAtlasElement.binding.end.x + 1) * fullAtlasElement.texture.widthFactor) / (fullAtlasElement.texture.width + 1f), ((fullAtlasElement.binding.end.y + 1) * fullAtlasElement.texture.heightFactor) / (fullAtlasElement.texture.height + 1f))
textureEnd = Vec2((textureEnd.x - textureStart.x) * progress, textureEnd.y)
hudElement.drawImage(start, Vec2(start.x + ourXDiff, end.y), hudMesh, fullAtlasElement, textureStart, textureEnd, z + 1)
}
}

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.hud.elements.other
import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.gui.rendering.hud.HUDElementProperties
import de.bixilon.minosoft.gui.rendering.hud.HUDMesh
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 glm_.vec2.Vec2
class CrosshairHUDElement(
hudRender: HUDRenderer,
) : HUDElement(hudRender) {
override val elementProperties = HUDElementProperties(
position = Vec2(0f, 0f),
xBinding = HUDElementProperties.PositionBindings.CENTER,
yBinding = HUDElementProperties.PositionBindings.CENTER,
scale = 1f,
enabled = true,
)
private lateinit var crosshairAtlasElement: HUDAtlasElement
private lateinit var crosshairRealSize: Vec2
override fun init() {
crosshairAtlasElement = hudRenderer.hudAtlasElements[ResourceLocation("minecraft:crosshair")]!!
crosshairRealSize = crosshairAtlasElement.binding.size * hudRenderer.hudScale.scale * elementProperties.scale
}
override fun prepare(hudMesh: HUDMesh) {
drawImage(getRealPosition(crosshairRealSize, elementProperties, RealTypes.START), getRealPosition(crosshairRealSize, elementProperties, RealTypes.END), hudMesh, crosshairAtlasElement, 1)
}
}

View File

@ -14,12 +14,14 @@
package de.bixilon.minosoft.gui.rendering.hud.elements.other package de.bixilon.minosoft.gui.rendering.hud.elements.other
import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames
import de.bixilon.minosoft.data.GameModes
import de.bixilon.minosoft.data.mappings.ResourceLocation import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.gui.rendering.hud.HUDElementProperties import de.bixilon.minosoft.gui.rendering.hud.HUDElementProperties
import de.bixilon.minosoft.gui.rendering.hud.HUDMesh import de.bixilon.minosoft.gui.rendering.hud.HUDMesh
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.ProgressBar
import glm_.glm import glm_.glm
import glm_.vec2.Vec2 import glm_.vec2.Vec2
@ -34,18 +36,29 @@ class HotbarHUDElement(
enabled = true, enabled = true,
) )
lateinit var hotbarBaseAtlas: HUDAtlasElement private val realScale = elementProperties.scale * hudRenderer.hudScale.scale
lateinit var hotbarSelectedSlotFrame: HUDAtlasElement private val elementPadding = 2 * realScale
private lateinit var hotbarBaseAtlasElement: HUDAtlasElement
private lateinit var hotbarBaseRealSize: Vec2 private lateinit var hotbarBaseRealSize: Vec2
private lateinit var hotbarSelectedSlotFrameAtlasElement: HUDAtlasElement
private lateinit var hotbarSelectedSlotFrameRealSize: Vec2 private lateinit var hotbarSelectedSlotFrameRealSize: Vec2
private lateinit var experienceBar: ProgressBar
override fun init() { override fun init() {
hotbarBaseAtlas = hudRenderer.hudImages[ResourceLocation("minecraft:hotbar_base")]!! hotbarBaseAtlasElement = hudRenderer.hudAtlasElements[ResourceLocation("minecraft:hotbar_base")]!!
hotbarBaseRealSize = hotbarBaseAtlas.binding.size * hudRenderer.hudScale.scale * elementProperties.scale hotbarBaseRealSize = hotbarBaseAtlasElement.binding.size * hudRenderer.hudScale.scale * elementProperties.scale
hotbarSelectedSlotFrame = hudRenderer.hudImages[ResourceLocation("minecraft:hotbar_selected_slot_frame")]!! hotbarSelectedSlotFrameAtlasElement = hudRenderer.hudAtlasElements[ResourceLocation("minecraft:hotbar_selected_slot_frame")]!!
hotbarSelectedSlotFrameRealSize = hotbarSelectedSlotFrame.binding.size * hudRenderer.hudScale.scale * elementProperties.scale hotbarSelectedSlotFrameRealSize = hotbarSelectedSlotFrameAtlasElement.binding.size * hudRenderer.hudScale.scale * elementProperties.scale
experienceBar = ProgressBar(
hudRenderer.hudAtlasElements[ResourceLocation("minecraft:experience_bar_empty")]!!,
hudRenderer.hudAtlasElements[ResourceLocation("minecraft:experience_bar_full")]!!,
this
)
for ((slotIndex, resourceLocation) in KeyBindingsNames.SELECT_HOTBAR_SLOTS.withIndex()) { for ((slotIndex, resourceLocation) in KeyBindingsNames.SELECT_HOTBAR_SLOTS.withIndex()) {
hudRenderer.renderWindow.registerKeyCallback(resourceLocation) { _, _ -> hudRenderer.renderWindow.registerKeyCallback(resourceLocation) { _, _ ->
@ -55,28 +68,35 @@ class HotbarHUDElement(
} }
enum class RealTypes {
START,
END
}
private fun drawBaseBar(hudMesh: HUDMesh) {
val hotbarStart = getRealPosition(hotbarBaseRealSize, elementProperties, RealTypes.START)
drawImage(hotbarStart, getRealPosition(hotbarBaseRealSize, elementProperties, RealTypes.END), hudMesh, hotbarBaseAtlas, 1)
val selectedSlotBinding = hotbarBaseAtlas.slots[hudRenderer.connection.player.selectedSlot] ?: return
val selectedSlotFrameBinding = hotbarSelectedSlotFrame.slots[0] ?: return
val slotSizeFactorDelta = glm.abs(Vec2(hotbarSelectedSlotFrame.binding.size - selectedSlotFrameBinding.size))
val selectedSlotStart = hotbarStart + selectedSlotBinding.start * hudRenderer.hudScale.scale * elementProperties.scale - slotSizeFactorDelta
val selectedSlotEnd = hotbarStart + selectedSlotBinding.end * hudRenderer.hudScale.scale * elementProperties.scale + slotSizeFactorDelta
drawImage(selectedSlotStart, selectedSlotEnd, hudMesh, hotbarSelectedSlotFrame, 2)
}
override fun prepare(hudMesh: HUDMesh) { override fun prepare(hudMesh: HUDMesh) {
drawBaseBar(hudMesh) if (hudRenderer.connection.player.gameMode == GameModes.SPECTATOR) {
return
}
// hotbar
val hotbarStart = getRealPosition(hotbarBaseRealSize, elementProperties, RealTypes.START)
val hotbarEnd = getRealPosition(hotbarBaseRealSize, elementProperties, RealTypes.END)
drawImage(hotbarStart, hotbarEnd, hudMesh, hotbarBaseAtlasElement, 1)
// selectedFrame
val selectedSlotBinding = hotbarBaseAtlasElement.slots[hudRenderer.connection.player.selectedSlot] ?: return
val selectedSlotFrameBinding = hotbarSelectedSlotFrameAtlasElement.slots[0] ?: return
val slotSizeFactorDelta = glm.abs(Vec2(hotbarSelectedSlotFrameAtlasElement.binding.size - selectedSlotFrameBinding.size))
val selectedSlotStart = hotbarStart + selectedSlotBinding.start * realScale - slotSizeFactorDelta + Vec2(0, realScale)
val selectedSlotEnd = hotbarStart + selectedSlotBinding.end * realScale + slotSizeFactorDelta + Vec2(realScale, realScale)
drawImage(selectedSlotStart, selectedSlotEnd, hudMesh, hotbarSelectedSlotFrameAtlasElement, 2)
if (hudRenderer.connection.player.gameMode == GameModes.CREATIVE) {
return
}
// experience bar
val experienceBarStart = Vec2(hotbarStart.x, (hotbarEnd.y + (experienceBar.size.y * realScale) + elementPadding))
val experienceBarEnd = Vec2(hotbarEnd.x, (hotbarEnd.y + elementPadding))
experienceBar.draw(hudMesh, experienceBarStart, experienceBarEnd, hudRenderer.connection.player.experienceBarProgress, 3)
} }
} }

View File

@ -151,7 +151,7 @@ class HUDDebugScreenElement(private val hudTextElement: HUDTextElement) : HUDTex
} }
private fun getScreenDimensions(): String { private fun getScreenDimensions(): String {
return "${hudTextElement.renderWindow.screenDimensions.x}x${hudTextElement.renderWindow.screenDimensions.y}" return "${hudTextElement.renderWindow.screenWidth}x${hudTextElement.renderWindow.screenHeight}"
} }
private fun getLocation(): String { private fun getLocation(): String {

View File

@ -39,6 +39,7 @@ class TextureArray(val textures: Collection<Texture>, val maxWidth: Int, val max
for (texture in textures) { for (texture in textures) {
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, texture.id, texture.width, texture.height, 1, GL_RGBA, GL_UNSIGNED_BYTE, texture.buffer) glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, texture.id, texture.width, texture.height, 1, GL_RGBA, GL_UNSIGNED_BYTE, texture.buffer)
texture.buffer.clear()
} }
glGenerateMipmap(GL_TEXTURE_2D_ARRAY) glGenerateMipmap(GL_TEXTURE_2D_ARRAY)
return textureId return textureId

View File

@ -83,14 +83,14 @@ public abstract class Network {
boolean success; boolean success;
try { try {
success = packet.read(data); success = packet.read(data);
if (data.getBytesLeft() > 0 || !success) {
throw new PacketParseException(String.format("Could not parse packet %s (used=%d, available=%d, total=%d, success=%s)", packetType, data.getPosition(), data.getBytesLeft(), data.getLength(), success));
}
packet.check(this.connection);
} catch (Throwable exception) { } catch (Throwable exception) {
packet.onError(this.connection); packet.onError(this.connection);
throw exception; throw exception;
} }
if (data.getBytesLeft() > 0 || !success) {
packet.onError(this.connection);
throw new PacketParseException(String.format("Could not parse packet %s (used=%d, available=%d, total=%d, success=%s)", packetType, data.getPosition(), data.getBytesLeft(), data.getLength(), success));
}
return packet; return packet;
} catch (Throwable e) { } catch (Throwable e) {
Log.protocol(String.format("An error occurred while parsing a packet (%s): %s", packetType, e)); Log.protocol(String.format("An error occurred while parsing a packet (%s): %s", packetType, e));

View File

@ -23,4 +23,6 @@ abstract class ClientboundPacket : Packet {
open fun handle(connection: Connection) {} open fun handle(connection: Connection) {}
open fun onError(connection: Connection) {} open fun onError(connection: Connection) {}
open fun check(connection: Connection) {}
} }

View File

@ -1,68 +0,0 @@
/*
* Minosoft
* Copyright (C) 2020 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.protocol.packets.clientbound.play;
import de.bixilon.minosoft.modding.event.events.ExperienceChangeEvent;
import de.bixilon.minosoft.protocol.network.Connection;
import de.bixilon.minosoft.protocol.packets.ClientboundPacket;
import de.bixilon.minosoft.protocol.protocol.InByteBuffer;
import de.bixilon.minosoft.util.logging.Log;
import static de.bixilon.minosoft.protocol.protocol.ProtocolVersions.V_14W04A;
public class PacketSetExperience extends ClientboundPacket {
float bar;
int level;
int total;
@Override
public boolean read(InByteBuffer buffer) {
this.bar = buffer.readFloat();
if (buffer.getVersionId() < V_14W04A) {
this.level = buffer.readUnsignedShort();
this.total = buffer.readUnsignedShort();
return true;
}
this.level = buffer.readVarInt();
this.total = buffer.readVarInt();
return true;
}
@Override
public void handle(Connection connection) {
if (connection.fireEvent(new ExperienceChangeEvent(connection, this))) {
return;
}
connection.getPlayer().setLevel(getLevel());
connection.getPlayer().setTotalExperience(getTotal());
}
@Override
public void log() {
Log.protocol(String.format("[IN] Level update received. Now at %d levels, totally %d exp", this.level, this.total));
}
public float getBar() {
return this.bar;
}
public int getLevel() {
return this.level;
}
public int getTotal() {
return this.total;
}
}

View File

@ -0,0 +1,60 @@
/*
* Minosoft
* Copyright (C) 2020 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.protocol.packets.clientbound.play
import de.bixilon.minosoft.modding.event.events.ExperienceChangeEvent
import de.bixilon.minosoft.protocol.network.Connection
import de.bixilon.minosoft.protocol.packets.ClientboundPacket
import de.bixilon.minosoft.protocol.protocol.InByteBuffer
import de.bixilon.minosoft.protocol.protocol.ProtocolVersions
import de.bixilon.minosoft.util.logging.Log
class PacketSetExperience : ClientboundPacket() {
var bar = 0f
private set
var level = 0
private set
var total = 0
private set
override fun read(buffer: InByteBuffer): Boolean {
bar = buffer.readFloat()
if (buffer.versionId < ProtocolVersions.V_14W04A) {
level = buffer.readUnsignedShort()
total = buffer.readUnsignedShort()
return true
}
level = buffer.readVarInt()
total = buffer.readVarInt()
return true
}
override fun check(connection: Connection) {
check(bar in 0.0f..1.0f) { "Bar is invalid!" }
check(level >= 0) { "Level is negative is invalid!" }
check(total >= 0) { "Total experience is negative!" }
}
override fun handle(connection: Connection) {
if (connection.fireEvent(ExperienceChangeEvent(connection, this))) {
return
}
connection.player.level = level
connection.player.experienceBarProgress = bar
connection.player.totalExperience = total
}
override fun log() {
Log.protocol("[IN] Level update received. Now at $level level(s), total $total experience, experience bar at $bar", level, total)
}
}

View File

@ -16,7 +16,7 @@
}, },
"2": { "2": {
"start": [43, 3], "start": [43, 3],
"end": [56, 18] "end": [58, 18]
}, },
"3": { "3": {
"start": [63, 3], "start": [63, 3],
@ -60,5 +60,32 @@
} }
} }
} }
},
"minecraft:crosshair": {
"texture": "minecraft:textures/gui/icons.png",
"versions": {
"0": {
"start": [0, 0],
"end": [15, 15]
}
}
},
"minecraft:experience_bar_empty": {
"texture": "minecraft:textures/gui/icons.png",
"versions": {
"0": {
"start": [0, 64],
"end": [181, 68]
}
}
},
"minecraft:experience_bar_full": {
"texture": "minecraft:textures/gui/icons.png",
"versions": {
"0": {
"start": [0, 69],
"end": [181, 73]
}
}
} }
} }

View File

@ -16,14 +16,17 @@
out vec4 outColor; out vec4 outColor;
in vec3 passTextureCoordinates; in vec3 passTextureCoordinates;
in vec4 passTintColor;
uniform sampler2DArray hudTextureArray; uniform sampler2DArray hudTextureArray;
void main() { void main() {
vec4 textureColor = texture(hudTextureArray, passTextureCoordinates); vec4 textureColor = texture(hudTextureArray, passTextureCoordinates);
if (textureColor.a == 0) { if (passTintColor.a == 1.0f && textureColor.a == 0) {
discard; discard;
} }
if (passTintColor.a != 0.0f){
textureColor *= passTintColor;
}
outColor = textureColor; outColor = textureColor;
} }

View File

@ -16,10 +16,13 @@
layout (location = 0) in vec3 inPosition; layout (location = 0) in vec3 inPosition;
layout (location = 1) in vec2 textureIndex; layout (location = 1) in vec2 textureIndex;
layout (location = 2) in uint textureLayer; layout (location = 2) in uint textureLayer;
layout (location = 3) in uint tintColor;
out vec3 passTextureCoordinates; out vec3 passTextureCoordinates;
out vec4 passTintColor;
void main() { void main() {
gl_Position = vec4(inPosition.xyz, 1.0f); gl_Position = vec4(inPosition.xyz, 1.0f);
passTextureCoordinates = vec3(textureIndex, textureLayer); passTextureCoordinates = vec3(textureIndex, textureLayer);
passTintColor = vec4(((tintColor >> 24u) & 0xFFu) / 255.0f, ((tintColor >> 16u) & 0xFFu) / 255.0f, ((tintColor >> 8u) & 0xFFu) / 255.0f, (tintColor & 0xFFu) / 255.0f);
} }