From 63eb03a17be24eea9b9c6d4964f13cd587f9de4e Mon Sep 17 00:00:00 2001 From: Bixilon Date: Thu, 4 Mar 2021 20:38:51 +0100 Subject: [PATCH] rendering: crosshair, improved hotbar, experience bar, network: add packet data check --- .../java/de/bixilon/minosoft/data/Player.kt | 1 + .../minosoft/gui/rendering/hud/HUDMesh.kt | 12 ++- .../minosoft/gui/rendering/hud/HUDRenderer.kt | 14 ++-- .../gui/rendering/hud/atlas/Vec2Binding.kt | 4 +- .../gui/rendering/hud/elements/HUDElement.kt | 26 +++++-- .../gui/rendering/hud/elements/ProgressBar.kt | 46 +++++++++++ .../hud/elements/other/CrosshairHUDElement.kt | 49 ++++++++++++ .../hud/elements/other/HotbarHUDElement.kt | 76 ++++++++++++------- .../elements/text/HUDDebugScreenElement.kt | 2 +- .../gui/rendering/textures/TextureArray.kt | 1 + .../minosoft/protocol/network/Network.java | 8 +- .../protocol/packets/ClientboundPacket.kt | 2 + .../clientbound/play/PacketSetExperience.java | 68 ----------------- .../clientbound/play/PacketSetExperience.kt | 60 +++++++++++++++ .../assets/minosoft/mapping/atlas.json | 29 ++++++- .../rendering/shader/hud_fragment.glsl | 7 +- .../minosoft/rendering/shader/hud_vertex.glsl | 3 + 17 files changed, 286 insertions(+), 122 deletions(-) create mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/ProgressBar.kt create mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/other/CrosshairHUDElement.kt delete mode 100644 src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketSetExperience.java create mode 100644 src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketSetExperience.kt diff --git a/src/main/java/de/bixilon/minosoft/data/Player.kt b/src/main/java/de/bixilon/minosoft/data/Player.kt index c9c9b87d5..b976b0f81 100644 --- a/src/main/java/de/bixilon/minosoft/data/Player.kt +++ b/src/main/java/de/bixilon/minosoft/data/Player.kt @@ -39,6 +39,7 @@ class Player(val account: Account) { var selectedSlot: Int = 0 var level = 0 var totalExperience = 0 + var experienceBarProgress = 0f var entity: PlayerEntity? = null var isSpawnConfirmed = false var playerUUID: UUID = account.uuid diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/HUDMesh.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/HUDMesh.kt index 5cd57a289..8d43fb044 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/HUDMesh.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/HUDMesh.kt @@ -13,6 +13,7 @@ package de.bixilon.minosoft.gui.rendering.hud +import de.bixilon.minosoft.data.text.RGBColor import de.bixilon.minosoft.gui.rendering.util.Mesh import glm_.BYTES import glm_.vec2.Vec2 @@ -32,21 +33,28 @@ class HUDMesh : Mesh() { glEnableVertexAttribArray(index++) glVertexAttribPointer(index, 1, GL_FLOAT, false, FLOATS_PER_VERTEX * Float.BYTES, (5 * Float.BYTES).toLong()) glEnableVertexAttribArray(index++) + glVertexAttribPointer(index, 1, GL_FLOAT, false, FLOATS_PER_VERTEX * Float.BYTES, (6 * Float.BYTES).toLong()) + glEnableVertexAttribArray(index++) 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.y) data.add(position.z) data.add(textureCoordinates.x) data.add(textureCoordinates.y) data.add(Float.fromBits(atlasPage)) + if (tintColor == null) { + data.add(0f) + } else { + data.add(Float.fromBits(tintColor.color)) + } } companion object { - private const val FLOATS_PER_VERTEX = 6 + private const val FLOATS_PER_VERTEX = 7 } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/HUDRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/HUDRenderer.kt index 378bdf693..595538dd5 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/HUDRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/HUDRenderer.kt @@ -19,6 +19,7 @@ import de.bixilon.minosoft.gui.rendering.RenderWindow import de.bixilon.minosoft.gui.rendering.Renderer 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.other.CrosshairHUDElement 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.shader.Shader @@ -37,10 +38,11 @@ class HUDRenderer(val connection: Connection, val renderWindow: RenderWindow) : val hudElements: MutableMap = mutableMapOf( ResourceLocation("minosoft:hud_text_renderer") to HUDTextElement(connection, this, renderWindow), 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")) - lateinit var hudTextures: TextureArray - lateinit var hudImages: Map + lateinit var hudAtlasTextures: TextureArray + lateinit var hudAtlasElements: Map var lastTickTime = 0L var orthographicMatrix: Mat4 = Mat4() private set @@ -51,10 +53,10 @@ class HUDRenderer(val connection: Connection, val renderWindow: RenderWindow) : 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) - this.hudImages = hudImages.second + this.hudAtlasElements = hudImages.second - hudTextures = TextureArray.createTextureArray(connection.version.assetsManager, hudImages.first.toSet()) - hudTextures.load() + hudAtlasTextures = TextureArray.createTextureArray(connection.version.assetsManager, hudImages.first.toSet()) + hudAtlasTextures.load() for (element in hudElements.values) { element.init() @@ -62,7 +64,7 @@ class HUDRenderer(val connection: Connection, val renderWindow: RenderWindow) : } override fun postInit() { - hudTextures.use(hudShader, "hudTextureArray") + hudAtlasTextures.use(hudShader, "hudTextureArray") for (element in hudElements.values) { element.postInit() } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/atlas/Vec2Binding.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/atlas/Vec2Binding.kt index eafa76b04..8fa971a9b 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/atlas/Vec2Binding.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/atlas/Vec2Binding.kt @@ -22,14 +22,14 @@ data class Vec2Binding( val start: Vec2, val end: Vec2, ) { - val size: Vec2 = glm.abs(Vec2(start - end)) + val size: Vec2 = glm.abs(Vec2(start - end)) + 1 companion object { fun deserialize(json: JsonElement): Vec2Binding { 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) }) } } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/HUDElement.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/HUDElement.kt index cbfdcb14c..385bddbd1 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/HUDElement.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/HUDElement.kt @@ -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.HUDRenderer 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_.vec3.Vec3 import glm_.vec4.Vec4 @@ -33,13 +32,13 @@ abstract class HUDElement(protected val hudRenderer: HUDRenderer) { 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 val halfElementSize = elementSize / 2f val realPosition = elementProperties.position * hudRenderer.renderWindow.screenDimensions 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 } else { halfSize @@ -63,14 +62,14 @@ abstract class HUDElement(protected val hudRenderer: HUDRenderer) { 0f } else { when (realType) { - HotbarHUDElement.RealTypes.START -> { + RealTypes.START -> { if (position < 0f) { position } else { position - (elementSize) } } - HotbarHUDElement.RealTypes.END -> { + RealTypes.END -> { if (position < 0f) { position + (elementSize) } 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) { + 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 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 + 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(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) } + + enum class RealTypes { + START, + END + } + companion object { private const val HUD_Z_COORDINATE = -0.9996f private const val HUD_Z_COORDINATE_Z_FACTOR = -0.000001f diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/ProgressBar.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/ProgressBar.kt new file mode 100644 index 000000000..b097c4c5e --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/ProgressBar.kt @@ -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 . + * + * 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) + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/other/CrosshairHUDElement.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/other/CrosshairHUDElement.kt new file mode 100644 index 000000000..531e2234b --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/other/CrosshairHUDElement.kt @@ -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 . + * + * 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) + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/other/HotbarHUDElement.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/other/HotbarHUDElement.kt index 3929c3dbb..66aafda97 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/other/HotbarHUDElement.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/other/HotbarHUDElement.kt @@ -14,12 +14,14 @@ package de.bixilon.minosoft.gui.rendering.hud.elements.other 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.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 de.bixilon.minosoft.gui.rendering.hud.elements.ProgressBar import glm_.glm import glm_.vec2.Vec2 @@ -34,18 +36,29 @@ class HotbarHUDElement( enabled = true, ) - lateinit var hotbarBaseAtlas: HUDAtlasElement - lateinit var hotbarSelectedSlotFrame: HUDAtlasElement + private val realScale = elementProperties.scale * hudRenderer.hudScale.scale + private val elementPadding = 2 * realScale + private lateinit var hotbarBaseAtlasElement: HUDAtlasElement private lateinit var hotbarBaseRealSize: Vec2 + private lateinit var hotbarSelectedSlotFrameAtlasElement: HUDAtlasElement private lateinit var hotbarSelectedSlotFrameRealSize: Vec2 + private lateinit var experienceBar: ProgressBar + + override fun init() { - hotbarBaseAtlas = hudRenderer.hudImages[ResourceLocation("minecraft:hotbar_base")]!! - hotbarBaseRealSize = hotbarBaseAtlas.binding.size * hudRenderer.hudScale.scale * elementProperties.scale - hotbarSelectedSlotFrame = hudRenderer.hudImages[ResourceLocation("minecraft:hotbar_selected_slot_frame")]!! - hotbarSelectedSlotFrameRealSize = hotbarSelectedSlotFrame.binding.size * hudRenderer.hudScale.scale * elementProperties.scale + hotbarBaseAtlasElement = hudRenderer.hudAtlasElements[ResourceLocation("minecraft:hotbar_base")]!! + hotbarBaseRealSize = hotbarBaseAtlasElement.binding.size * hudRenderer.hudScale.scale * elementProperties.scale + hotbarSelectedSlotFrameAtlasElement = hudRenderer.hudAtlasElements[ResourceLocation("minecraft:hotbar_selected_slot_frame")]!! + 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()) { 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) { - 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) } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/text/HUDDebugScreenElement.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/text/HUDDebugScreenElement.kt index eb271a6bb..7f43c033f 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/text/HUDDebugScreenElement.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/text/HUDDebugScreenElement.kt @@ -151,7 +151,7 @@ class HUDDebugScreenElement(private val hudTextElement: HUDTextElement) : HUDTex } 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 { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/textures/TextureArray.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/textures/TextureArray.kt index 1583f0f95..e1c377cf2 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/textures/TextureArray.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/textures/TextureArray.kt @@ -39,6 +39,7 @@ class TextureArray(val textures: Collection, val maxWidth: Int, val max 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) + texture.buffer.clear() } glGenerateMipmap(GL_TEXTURE_2D_ARRAY) return textureId diff --git a/src/main/java/de/bixilon/minosoft/protocol/network/Network.java b/src/main/java/de/bixilon/minosoft/protocol/network/Network.java index 20a7fdb0d..bb3a266e3 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/network/Network.java +++ b/src/main/java/de/bixilon/minosoft/protocol/network/Network.java @@ -83,14 +83,14 @@ public abstract class Network { boolean success; try { 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) { packet.onError(this.connection); 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; } catch (Throwable e) { Log.protocol(String.format("An error occurred while parsing a packet (%s): %s", packetType, e)); diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/ClientboundPacket.kt b/src/main/java/de/bixilon/minosoft/protocol/packets/ClientboundPacket.kt index 4effd6feb..82c8c7341 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/ClientboundPacket.kt +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/ClientboundPacket.kt @@ -23,4 +23,6 @@ abstract class ClientboundPacket : Packet { open fun handle(connection: Connection) {} open fun onError(connection: Connection) {} + + open fun check(connection: Connection) {} } diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketSetExperience.java b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketSetExperience.java deleted file mode 100644 index 2ded41317..000000000 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketSetExperience.java +++ /dev/null @@ -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 . - * - * 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; - } -} diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketSetExperience.kt b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketSetExperience.kt new file mode 100644 index 000000000..66a7762ea --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketSetExperience.kt @@ -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 . + * + * 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) + } +} diff --git a/src/main/resources/assets/minosoft/mapping/atlas.json b/src/main/resources/assets/minosoft/mapping/atlas.json index 2ce093568..f9c7e2241 100644 --- a/src/main/resources/assets/minosoft/mapping/atlas.json +++ b/src/main/resources/assets/minosoft/mapping/atlas.json @@ -16,7 +16,7 @@ }, "2": { "start": [43, 3], - "end": [56, 18] + "end": [58, 18] }, "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] + } + } } } diff --git a/src/main/resources/assets/minosoft/rendering/shader/hud_fragment.glsl b/src/main/resources/assets/minosoft/rendering/shader/hud_fragment.glsl index 478f0a453..c3f852cf4 100644 --- a/src/main/resources/assets/minosoft/rendering/shader/hud_fragment.glsl +++ b/src/main/resources/assets/minosoft/rendering/shader/hud_fragment.glsl @@ -16,14 +16,17 @@ out vec4 outColor; in vec3 passTextureCoordinates; +in vec4 passTintColor; uniform sampler2DArray hudTextureArray; - void main() { vec4 textureColor = texture(hudTextureArray, passTextureCoordinates); - if (textureColor.a == 0) { + if (passTintColor.a == 1.0f && textureColor.a == 0) { discard; } + if (passTintColor.a != 0.0f){ + textureColor *= passTintColor; + } outColor = textureColor; } diff --git a/src/main/resources/assets/minosoft/rendering/shader/hud_vertex.glsl b/src/main/resources/assets/minosoft/rendering/shader/hud_vertex.glsl index 1c91bcf14..d9e0b242e 100644 --- a/src/main/resources/assets/minosoft/rendering/shader/hud_vertex.glsl +++ b/src/main/resources/assets/minosoft/rendering/shader/hud_vertex.glsl @@ -16,10 +16,13 @@ layout (location = 0) in vec3 inPosition; layout (location = 1) in vec2 textureIndex; layout (location = 2) in uint textureLayer; +layout (location = 3) in uint tintColor; out vec3 passTextureCoordinates; +out vec4 passTintColor; void main() { gl_Position = vec4(inPosition.xyz, 1.0f); 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); }