mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-12 17:07:55 -04:00
rendering: introduce new hud system
This commit is contained in:
parent
8eee74df5d
commit
66a726423e
@ -14,8 +14,8 @@
|
||||
package de.bixilon.minosoft.config.config.game.elements
|
||||
|
||||
import de.bixilon.minosoft.data.mappings.ResourceLocation
|
||||
import de.bixilon.minosoft.gui.rendering.hud.HUDElementProperties
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.HUDElement
|
||||
|
||||
data class ElementsGameConfig(
|
||||
val entries: MutableMap<ResourceLocation, HUDElementProperties> = mutableMapOf(),
|
||||
val entries: MutableMap<ResourceLocation, HUDElement> = mutableMapOf(),
|
||||
)
|
||||
|
@ -17,12 +17,7 @@ import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonObject
|
||||
import de.bixilon.minosoft.data.locale.minecraft.Translator
|
||||
import de.bixilon.minosoft.data.text.RGBColor.Companion.asColor
|
||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||
import de.bixilon.minosoft.gui.rendering.font.text.TextGetProperties
|
||||
import de.bixilon.minosoft.gui.rendering.font.text.TextSetProperties
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.LabelNode
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||
import glm_.vec2.Vec2i
|
||||
import javafx.collections.ObservableList
|
||||
import javafx.scene.Node
|
||||
import java.text.CharacterIterator
|
||||
@ -178,12 +173,6 @@ class BaseComponent : ChatComponent {
|
||||
return nodes
|
||||
}
|
||||
|
||||
override fun prepareRender(startPosition: Vec2i, offset: Vec2i, renderWindow: RenderWindow, textElement: LabelNode, z: Int, setProperties: TextSetProperties, getProperties: TextGetProperties) {
|
||||
for (part in parts) {
|
||||
part.prepareRender(startPosition, offset, renderWindow, textElement, z, setProperties, getProperties)
|
||||
}
|
||||
}
|
||||
|
||||
override fun applyDefaultColor(color: RGBColor) {
|
||||
for (part in parts) {
|
||||
part.applyDefaultColor(color)
|
||||
|
@ -17,11 +17,6 @@ import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonParser
|
||||
import com.google.gson.JsonPrimitive
|
||||
import de.bixilon.minosoft.data.locale.minecraft.Translator
|
||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||
import de.bixilon.minosoft.gui.rendering.font.text.TextGetProperties
|
||||
import de.bixilon.minosoft.gui.rendering.font.text.TextSetProperties
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.LabelNode
|
||||
import glm_.vec2.Vec2i
|
||||
import javafx.collections.FXCollections
|
||||
import javafx.collections.ObservableList
|
||||
import javafx.scene.Node
|
||||
@ -59,11 +54,6 @@ interface ChatComponent {
|
||||
fun applyDefaultColor(color: RGBColor)
|
||||
|
||||
|
||||
/**
|
||||
* Prepares the chat component for rendering (used in opengl)
|
||||
*/
|
||||
fun prepareRender(startPosition: Vec2i, offset: Vec2i, renderWindow: RenderWindow, textElement: LabelNode, z: Int, setProperties: TextSetProperties, getProperties: TextGetProperties)
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmOverloads
|
||||
|
@ -13,17 +13,8 @@
|
||||
package de.bixilon.minosoft.data.text
|
||||
|
||||
import de.bixilon.minosoft.Minosoft
|
||||
import de.bixilon.minosoft.gui.rendering.RenderConstants
|
||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||
import de.bixilon.minosoft.gui.rendering.font.Font
|
||||
import de.bixilon.minosoft.gui.rendering.font.text.TextGetProperties
|
||||
import de.bixilon.minosoft.gui.rendering.font.text.TextSetProperties
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.ImageNode
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.LabelNode
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.properties.NodeSizing
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||
import de.bixilon.minosoft.util.Util
|
||||
import glm_.vec2.Vec2i
|
||||
import javafx.animation.Animation
|
||||
import javafx.animation.KeyFrame
|
||||
import javafx.animation.Timeline
|
||||
@ -161,52 +152,4 @@ open class TextComponent(
|
||||
nodes.add(text)
|
||||
return nodes
|
||||
}
|
||||
|
||||
|
||||
override fun prepareRender(startPosition: Vec2i, offset: Vec2i, renderWindow: RenderWindow, textElement: LabelNode, z: Int, setProperties: TextSetProperties, getProperties: TextGetProperties) {
|
||||
val color = this.color ?: ProtocolDefinition.DEFAULT_COLOR
|
||||
|
||||
|
||||
// bring chars in right order and reverse them if right bound
|
||||
val charArray = this.message.toCharArray().toList()
|
||||
|
||||
fun checkGetSize(charEnd: Vec2i) {
|
||||
if (charEnd.x > getProperties.size.x) {
|
||||
getProperties.size.x = charEnd.x
|
||||
}
|
||||
if (charEnd.y > getProperties.size.y) {
|
||||
getProperties.size.y = charEnd.y
|
||||
}
|
||||
}
|
||||
|
||||
fun pushNewLine() {
|
||||
offset.x = 0
|
||||
offset.y += Font.CHAR_HEIGHT + RenderConstants.TEXT_LINE_PADDING
|
||||
|
||||
checkGetSize(Vec2i(0, 0))
|
||||
}
|
||||
|
||||
// add all chars
|
||||
for (char in charArray) {
|
||||
if (ProtocolDefinition.LINE_BREAK_CHARS.contains(char)) {
|
||||
pushNewLine()
|
||||
continue
|
||||
}
|
||||
val fontChar = renderWindow.font.getChar(char)
|
||||
val charSize = fontChar.size
|
||||
|
||||
var charStart = Vec2i(offset)
|
||||
var charEnd = charStart + charSize
|
||||
|
||||
if (charEnd.x >= setProperties.hardWrap) {
|
||||
pushNewLine()
|
||||
charStart = Vec2i(offset)
|
||||
charEnd = charStart + charSize
|
||||
}
|
||||
textElement.addChild(charStart + startPosition, ImageNode(renderWindow, NodeSizing(minSize = charSize), fontChar, 1, color))
|
||||
offset.x += charSize.x + Font.SPACE_BETWEEN_CHARS
|
||||
|
||||
checkGetSize(charEnd)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,23 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
import de.bixilon.minosoft.gui.rendering.util.mesh.SimpleTextureMesh
|
||||
|
||||
class HUDMesh : SimpleTextureMesh() {
|
||||
|
||||
fun addCacheMesh(cacheMesh: HUDCacheMesh) {
|
||||
data.addAll(cacheMesh.cache)
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
import de.bixilon.minosoft.data.mappings.CompanionResourceLocation
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.HUDElement
|
||||
|
||||
interface HUDRenderBuilder<T : HUDElement> : CompanionResourceLocation {
|
||||
val DEFAULT_PROPERTIES: HUDElementProperties
|
||||
|
||||
fun build(hudRenderer: HUDRenderer): T
|
||||
}
|
@ -21,120 +21,57 @@ import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||
import de.bixilon.minosoft.gui.rendering.Renderer
|
||||
import de.bixilon.minosoft.gui.rendering.RendererBuilder
|
||||
import de.bixilon.minosoft.gui.rendering.hud.atlas.HUDAtlasElement
|
||||
import de.bixilon.minosoft.gui.rendering.hud.elements.other.BreakProgressHUDElement
|
||||
import de.bixilon.minosoft.gui.rendering.hud.elements.other.CrosshairHUDElement
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.HUDElement
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.chat.ChatBoxHUDElement
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.debug.HUDSystemDebugNode
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.debug.HUDWorldDebugNode
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.HUDElement
|
||||
import de.bixilon.minosoft.gui.rendering.modding.events.ScreenResizeEvent
|
||||
import de.bixilon.minosoft.gui.rendering.shader.Shader
|
||||
import de.bixilon.minosoft.modding.event.CallbackEventInvoker
|
||||
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||
import de.bixilon.minosoft.util.MMath
|
||||
import de.bixilon.minosoft.util.json.ResourceLocationJsonMap.toResourceLocationMap
|
||||
import glm_.glm
|
||||
import glm_.mat4x4.Mat4
|
||||
import glm_.vec2.Vec2i
|
||||
|
||||
class HUDRenderer(val connection: PlayConnection, val renderWindow: RenderWindow) : Renderer {
|
||||
private val hudElements: MutableMap<ResourceLocation, Pair<HUDElementProperties, HUDElement>> = mutableMapOf()
|
||||
private val enabledHUDElement: MutableMap<ResourceLocation, Pair<HUDElementProperties, HUDElement>> = mutableMapOf()
|
||||
private val hudElements: MutableMap<ResourceLocation, HUDElement> = mutableMapOf()
|
||||
private val enabledHUDElements: MutableMap<ResourceLocation, HUDElement> = mutableMapOf()
|
||||
private val hudShader = Shader(
|
||||
resourceLocation = ResourceLocation(ProtocolDefinition.MINOSOFT_NAMESPACE, "hud"),
|
||||
)
|
||||
lateinit var hudAtlasElements: Map<ResourceLocation, HUDAtlasElement>
|
||||
var orthographicMatrix: Mat4 = Mat4()
|
||||
private set
|
||||
var currentHUDMesh: HUDMesh = HUDMesh()
|
||||
|
||||
private var hudEnabled = true
|
||||
|
||||
private var forcePrepare = true
|
||||
|
||||
|
||||
override fun init() {
|
||||
hudShader.load(Minosoft.MINOSOFT_ASSETS_MANAGER)
|
||||
|
||||
this.hudAtlasElements = HUDAtlasElement.deserialize(Minosoft.MINOSOFT_ASSETS_MANAGER.readJsonAsset(ResourceLocation(ProtocolDefinition.MINOSOFT_NAMESPACE, "mapping/atlas.json")).toResourceLocationMap(), renderWindow.textures.allTextures)
|
||||
hudAtlasElements = HUDAtlasElement.deserialize(Minosoft.MINOSOFT_ASSETS_MANAGER.readJsonAsset(ResourceLocation(ProtocolDefinition.MINOSOFT_NAMESPACE, "mapping/atlas.json")).toResourceLocationMap(), renderWindow.textures.allTextures)
|
||||
|
||||
|
||||
|
||||
registerDefaultElements()
|
||||
registerElements()
|
||||
|
||||
renderWindow.inputHandler.registerKeyCallback(KeyBindingsNames.TOGGLE_HUD) {
|
||||
hudEnabled = !hudEnabled
|
||||
}
|
||||
|
||||
for ((_, element) in hudElements.values) {
|
||||
element.init()
|
||||
}
|
||||
|
||||
renderWindow.inputHandler.registerKeyCallback(KeyBindingsNames.CLOSE) {
|
||||
|
||||
}
|
||||
|
||||
connection.registerEvent(CallbackEventInvoker.of<ScreenResizeEvent> {
|
||||
orthographicMatrix = glm.ortho(-it.screenDimensions.x / 2.0f, it.screenDimensions.x / 2.0f, -it.screenDimensions.y / 2.0f, it.screenDimensions.y / 2.0f)
|
||||
for ((_, hudElement) in hudElements.values) {
|
||||
hudElement.layout.clearChildrenCache()
|
||||
orthographicMatrix = glm.ortho(0f, renderWindow.screenDimensions.x.toFloat(), renderWindow.screenDimensions.y.toFloat(), 0f)
|
||||
for (hudElement in hudElements.values) {
|
||||
hudElement.prepare(orthographicMatrix)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun registerDefaultElements() {
|
||||
addElement(BreakProgressHUDElement)
|
||||
addElement(CrosshairHUDElement)
|
||||
|
||||
addElement(HUDWorldDebugNode)
|
||||
addElement(HUDSystemDebugNode)
|
||||
addElement(ChatBoxHUDElement)
|
||||
}
|
||||
|
||||
fun addElement(builder: HUDRenderBuilder<*>) {
|
||||
var needToSafeConfig = false
|
||||
val properties = Minosoft.getConfig().config.game.elements.entries.getOrPut(builder.RESOURCE_LOCATION) {
|
||||
needToSafeConfig = true
|
||||
builder.DEFAULT_PROPERTIES
|
||||
private fun registerElements() {
|
||||
for ((resourceLocation, hudElement) in Minosoft.getConfig().config.game.elements.entries.entries) {
|
||||
hudElements[resourceLocation] = hudElement
|
||||
enabledHUDElements[resourceLocation] = hudElement
|
||||
hudElement.init(this)
|
||||
}
|
||||
if (needToSafeConfig) {
|
||||
Minosoft.getConfig().saveToFile()
|
||||
}
|
||||
val hudElement = builder.build(this)
|
||||
hudElement.properties = properties
|
||||
val pair = Pair(properties, hudElement)
|
||||
hudElements[builder.RESOURCE_LOCATION] = pair
|
||||
|
||||
|
||||
properties.toggleKeyBinding?.let {
|
||||
// register key binding
|
||||
renderWindow.inputHandler.registerKeyCallback(it) {
|
||||
// ToDo: Use sticky
|
||||
if (enabledHUDElement.contains(builder.RESOURCE_LOCATION)) {
|
||||
enabledHUDElement.remove(builder.RESOURCE_LOCATION)
|
||||
} else {
|
||||
enabledHUDElement[builder.RESOURCE_LOCATION] = pair
|
||||
}
|
||||
forcePrepare = true
|
||||
}
|
||||
}
|
||||
|
||||
if (properties.enabled) {
|
||||
enabledHUDElement[builder.RESOURCE_LOCATION] = pair
|
||||
forcePrepare = true
|
||||
}
|
||||
}
|
||||
|
||||
fun removeElement(resourceLocation: ResourceLocation) {
|
||||
val element = hudElements[resourceLocation] ?: return
|
||||
|
||||
element.first.toggleKeyBinding?.let {
|
||||
renderWindow.inputHandler.unregisterKeyBinding(it)
|
||||
}
|
||||
enabledHUDElement.remove(resourceLocation)
|
||||
hudElements.remove(resourceLocation)
|
||||
forcePrepare = true
|
||||
}
|
||||
|
||||
override fun postInit() {
|
||||
@ -145,74 +82,17 @@ class HUDRenderer(val connection: PlayConnection, val renderWindow: RenderWindow
|
||||
renderWindow.textures.use(hudShader)
|
||||
|
||||
for (element in hudElements.values) {
|
||||
element.second.postInit()
|
||||
element.postInit()
|
||||
}
|
||||
}
|
||||
|
||||
override fun draw() {
|
||||
if (!RenderConstants.RENDER_HUD) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!hudEnabled) {
|
||||
return
|
||||
}
|
||||
var needsUpdate = false
|
||||
val tempMesh = HUDMesh()
|
||||
|
||||
for ((_, hudElement) in enabledHUDElement.values) {
|
||||
hudElement.draw()
|
||||
|
||||
if (hudElement.layout.needsCacheUpdate()) {
|
||||
needsUpdate = true
|
||||
// break
|
||||
if (RenderConstants.RENDER_HUD && hudEnabled) {
|
||||
hudShader.use()
|
||||
for (hudElement in enabledHUDElements.values) {
|
||||
hudElement.draw()
|
||||
}
|
||||
}
|
||||
|
||||
if (forcePrepare || needsUpdate) {
|
||||
for ((elementProperties, hudElement) in enabledHUDElement.values) {
|
||||
val realScaleFactor = elementProperties.scale * Minosoft.getConfig().config.game.hud.scale
|
||||
val realSize = hudElement.layout.sizing.currentSize * realScaleFactor
|
||||
realSize.x = MMath.clamp(realSize.x, hudElement.layout.sizing.minSize.x, hudElement.layout.sizing.maxSize.x)
|
||||
realSize.y = MMath.clamp(realSize.y, hudElement.layout.sizing.minSize.y, hudElement.layout.sizing.maxSize.y)
|
||||
|
||||
val elementStart = getRealPosition(realSize, elementProperties, renderWindow.screenDimensions)
|
||||
|
||||
hudElement.layout.checkCache(elementStart, realScaleFactor, orthographicMatrix, 0)
|
||||
tempMesh.addCacheMesh(hudElement.layout.cache)
|
||||
}
|
||||
currentHUDMesh.unload(false)
|
||||
tempMesh.load()
|
||||
currentHUDMesh = tempMesh
|
||||
}
|
||||
hudShader.use()
|
||||
currentHUDMesh.draw()
|
||||
}
|
||||
|
||||
|
||||
private fun getRealPosition(elementSize: Vec2i, elementProperties: HUDElementProperties, screenDimensions: Vec2i): Vec2i {
|
||||
val halfScreenDimensions = screenDimensions / 2
|
||||
val halfElementSize = elementSize / 2
|
||||
val realPosition = elementProperties.position * halfScreenDimensions
|
||||
|
||||
var x = realPosition.x
|
||||
var y = realPosition.y
|
||||
if (elementProperties.xBinding == HUDElementProperties.PositionBindings.FURTHEST_POINT_AWAY) {
|
||||
if (elementProperties.position.x >= 0) {
|
||||
x -= elementSize.x
|
||||
}
|
||||
} else {
|
||||
x -= halfElementSize.x
|
||||
}
|
||||
|
||||
if (elementProperties.yBinding == HUDElementProperties.PositionBindings.FURTHEST_POINT_AWAY) {
|
||||
if (elementProperties.position.y < 0) {
|
||||
y += elementSize.y
|
||||
}
|
||||
} else {
|
||||
y += halfElementSize.y
|
||||
}
|
||||
return Vec2i(x, y)
|
||||
}
|
||||
|
||||
companion object : RendererBuilder<HUDRenderer> {
|
||||
|
@ -32,6 +32,14 @@ data class HUDAtlasElement(
|
||||
override val size: Vec2i
|
||||
get() = binding.size
|
||||
|
||||
val uvs: Array<Vec2> get() {
|
||||
return arrayOf(
|
||||
Vec2(uvStart.x, uvStart.y),
|
||||
Vec2(uvStart.x, uvEnd.y),
|
||||
Vec2(uvEnd.x, uvStart.y),
|
||||
Vec2(uvEnd.x, uvEnd.y),
|
||||
)
|
||||
}
|
||||
|
||||
fun postInit() {
|
||||
uvStart = (Vec2(binding.start) + RenderConstants.PIXEL_UV_PIXEL_ADD) * texture.arraySinglePixelFactor
|
||||
|
@ -25,7 +25,6 @@ data class Vec2Binding(
|
||||
val size: Vec2i = glm.abs(start - end)
|
||||
|
||||
companion object {
|
||||
|
||||
fun deserialize(json: JsonElement): Vec2Binding {
|
||||
check(json is JsonObject)
|
||||
|
||||
|
@ -1,146 +0,0 @@
|
||||
/*
|
||||
* 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.input
|
||||
|
||||
import de.bixilon.minosoft.config.key.KeyCodes
|
||||
import de.bixilon.minosoft.data.text.ChatComponent
|
||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.layout.AbsoluteLayout
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.LabelNode
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.properties.NodeSizing
|
||||
import de.bixilon.minosoft.util.MMath
|
||||
import glm_.vec2.Vec2i
|
||||
|
||||
|
||||
open class TextField(
|
||||
renderWindow: RenderWindow,
|
||||
val properties: TextFieldProperties,
|
||||
sizing: NodeSizing = NodeSizing(),
|
||||
) : AbsoluteLayout(renderWindow, sizing = sizing), KeyConsumer, MouseConsumer {
|
||||
private var textBuilder: StringBuilder = StringBuilder(properties.defaultText)
|
||||
val textElement = LabelNode(renderWindow, sizing = sizing.copy(), text = ChatComponent.of(text))
|
||||
private var position = text.length
|
||||
|
||||
var text: String
|
||||
get() = textBuilder.toString()
|
||||
set(value) {
|
||||
position = value.length
|
||||
textBuilder = StringBuilder(value)
|
||||
update()
|
||||
}
|
||||
|
||||
init {
|
||||
addChild(Vec2i(0, 0), textElement)
|
||||
clearChildrenCache()
|
||||
}
|
||||
|
||||
fun clearText() {
|
||||
textBuilder.clear()
|
||||
update()
|
||||
}
|
||||
|
||||
private fun update() {
|
||||
textElement.text = ChatComponent.of(text)
|
||||
}
|
||||
|
||||
override fun keyInput(keyCodes: KeyCodes) {
|
||||
when (keyCodes) {
|
||||
KeyCodes.KEY_BACKSPACE -> {
|
||||
if (textBuilder.isEmpty() || position == 0) {
|
||||
return
|
||||
}
|
||||
textBuilder.deleteCharAt(--position)
|
||||
}
|
||||
KeyCodes.KEY_DELETE -> {
|
||||
if (textBuilder.isEmpty() || position == textBuilder.length) {
|
||||
return
|
||||
}
|
||||
textBuilder.deleteCharAt(position)
|
||||
}
|
||||
KeyCodes.KEY_ENTER -> {
|
||||
if (renderWindow.inputHandler.isKeyDown(KeyCodes.KEY_LEFT_CONTROL, KeyCodes.KEY_RIGHT_CONTROL, KeyCodes.KEY_LEFT_SHIFT, KeyCodes.KEY_RIGHT_SHIFT)) {
|
||||
// new line
|
||||
if (position > properties.maxLength) {
|
||||
return
|
||||
}
|
||||
textBuilder.insert(position++, '\n')
|
||||
return
|
||||
}
|
||||
properties.onSubmit(text)
|
||||
if (properties.submitCloses) {
|
||||
properties.onClose()
|
||||
}
|
||||
text = properties.defaultText
|
||||
}
|
||||
KeyCodes.KEY_LEFT -> {
|
||||
position = MMath.clamp(position - 1, 0, text.length)
|
||||
return
|
||||
}
|
||||
KeyCodes.KEY_RIGHT -> {
|
||||
position = MMath.clamp(position + 1, 0, text.length)
|
||||
return
|
||||
}
|
||||
KeyCodes.KEY_V -> {
|
||||
if (renderWindow.inputHandler.isKeyDown(KeyCodes.KEY_LEFT_CONTROL, KeyCodes.KEY_RIGHT_CONTROL)) {
|
||||
// paste
|
||||
textInput(renderWindow.getClipboardText())
|
||||
}
|
||||
}
|
||||
// ToDo: Up and down for line breaks, shift and ctrl modifier, ...
|
||||
else -> {
|
||||
return
|
||||
}
|
||||
}
|
||||
update()
|
||||
super.keyInput(keyCodes)
|
||||
}
|
||||
|
||||
override fun tick(tick: Long) {
|
||||
if ((tick / FIELD_CURSOR_BLINK_INTERVAL) % 2L == 0L && position == text.length) {
|
||||
textElement.sText = "$textBuilder" + "_"
|
||||
} else {
|
||||
textElement.sText = textBuilder.toString()
|
||||
}
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
properties.onClose()
|
||||
}
|
||||
|
||||
override fun charInput(char: Char) {
|
||||
if (position >= properties.maxLength) {
|
||||
return
|
||||
}
|
||||
val previous = textBuilder.toString()
|
||||
textBuilder.insert(position++, char.toString())
|
||||
properties.onInput(previous, textBuilder.toString())
|
||||
update()
|
||||
}
|
||||
|
||||
fun textInput(text: String) {
|
||||
if (position >= properties.maxLength) {
|
||||
return
|
||||
}
|
||||
val length = MMath.clamp(text.length, 0, properties.maxLength - position)
|
||||
val previous = textBuilder.toString()
|
||||
textBuilder.insert(position, text.substring(0, length))
|
||||
position += length
|
||||
properties.onInput(previous, textBuilder.toString())
|
||||
update()
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val FIELD_CURSOR_BLINK_INTERVAL = 8
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
/*
|
||||
* 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.input
|
||||
|
||||
data class TextFieldProperties(
|
||||
var defaultText: String = "",
|
||||
var maxLength: Int = 256,
|
||||
var onSubmit: (text: String) -> Unit = {},
|
||||
var onClose: () -> Unit = {},
|
||||
var onInput: (previousText: String, nextText: String) -> Unit = { _, _ -> },
|
||||
var submitCloses: Boolean = false,
|
||||
)
|
@ -1,67 +0,0 @@
|
||||
/*
|
||||
* 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.data.text.ChatColors
|
||||
import de.bixilon.minosoft.data.text.TextComponent
|
||||
import de.bixilon.minosoft.gui.rendering.hud.HUDElementProperties
|
||||
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderBuilder
|
||||
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.HUDElement
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.layout.AbsoluteLayout
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.LabelNode
|
||||
import glm_.vec2.Vec2
|
||||
import glm_.vec2.Vec2i
|
||||
|
||||
class BreakProgressHUDElement(
|
||||
hudRenderer: HUDRenderer,
|
||||
) : HUDElement(hudRenderer) {
|
||||
override val layout = AbsoluteLayout(hudRenderer.renderWindow)
|
||||
|
||||
private val text: LabelNode = LabelNode(hudRenderer.renderWindow)
|
||||
|
||||
override fun init() {
|
||||
layout.addChild(Vec2i(0, 0), text)
|
||||
}
|
||||
|
||||
override fun draw() {
|
||||
val currentProgress = hudRenderer.renderWindow.inputHandler.leftClickHandler.breakProgress
|
||||
if (currentProgress in 0.0..1.0) {
|
||||
val textComponent = TextComponent("${(currentProgress * 100).toInt()}%")
|
||||
textComponent.color(when {
|
||||
currentProgress < 0.3 -> ChatColors.RED
|
||||
currentProgress < 0.7 -> ChatColors.YELLOW
|
||||
else -> ChatColors.GREEN
|
||||
})
|
||||
text.text = textComponent
|
||||
} else {
|
||||
// Toggle visibility?
|
||||
text.sText = ""
|
||||
}
|
||||
}
|
||||
|
||||
companion object : HUDRenderBuilder<BreakProgressHUDElement> {
|
||||
override val RESOURCE_LOCATION = ResourceLocation("minosoft:break_progress")
|
||||
override val DEFAULT_PROPERTIES = HUDElementProperties(
|
||||
position = Vec2(0.08f, 0.0f),
|
||||
xBinding = HUDElementProperties.PositionBindings.CENTER,
|
||||
yBinding = HUDElementProperties.PositionBindings.CENTER,
|
||||
)
|
||||
|
||||
override fun build(hudRenderer: HUDRenderer): BreakProgressHUDElement {
|
||||
return BreakProgressHUDElement(hudRenderer)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
/*
|
||||
* 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.HUDRenderBuilder
|
||||
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.HUDElement
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.layout.AbsoluteLayout
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.ImageNode
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.properties.NodeSizing
|
||||
import glm_.vec2.Vec2
|
||||
import glm_.vec2.Vec2i
|
||||
|
||||
class CrosshairHUDElement(
|
||||
hudRenderer: HUDRenderer,
|
||||
) : HUDElement(hudRenderer) {
|
||||
override val layout = AbsoluteLayout(hudRenderer.renderWindow)
|
||||
private lateinit var crosshairImage: ImageNode
|
||||
|
||||
override fun init() {
|
||||
val atlasElement = hudRenderer.hudAtlasElements[ResourceLocation("minecraft:crosshair")]!!
|
||||
crosshairImage = ImageNode(hudRenderer.renderWindow, NodeSizing(minSize = atlasElement.binding.size), textureLike = atlasElement)
|
||||
layout.addChild(Vec2i(0, 0), crosshairImage)
|
||||
}
|
||||
|
||||
companion object : HUDRenderBuilder<CrosshairHUDElement> {
|
||||
override val RESOURCE_LOCATION = ResourceLocation("minosoft:crosshair")
|
||||
override val DEFAULT_PROPERTIES = HUDElementProperties(
|
||||
position = Vec2(0.0f, 0.0f),
|
||||
xBinding = HUDElementProperties.PositionBindings.CENTER,
|
||||
yBinding = HUDElementProperties.PositionBindings.CENTER,
|
||||
)
|
||||
|
||||
override fun build(hudRenderer: HUDRenderer): CrosshairHUDElement {
|
||||
return CrosshairHUDElement(hudRenderer)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
/*
|
||||
* 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.nodes.chat
|
||||
|
||||
|
||||
import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames
|
||||
import de.bixilon.minosoft.data.mappings.ResourceLocation
|
||||
import de.bixilon.minosoft.gui.rendering.hud.HUDElementProperties
|
||||
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderBuilder
|
||||
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.hud.elements.input.TextField
|
||||
import de.bixilon.minosoft.gui.rendering.hud.elements.input.TextFieldProperties
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.HUDElement
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.layout.AbsoluteLayout
|
||||
import de.bixilon.minosoft.gui.rendering.modding.events.ScreenResizeEvent
|
||||
import de.bixilon.minosoft.modding.event.CallbackEventInvoker
|
||||
import glm_.vec2.Vec2
|
||||
import glm_.vec2.Vec2i
|
||||
|
||||
class ChatBoxHUDElement(hudRenderer: HUDRenderer) : HUDElement(hudRenderer) {
|
||||
override val layout = AbsoluteLayout(hudRenderer.renderWindow)
|
||||
private lateinit var inputField: TextField
|
||||
|
||||
override fun init() {
|
||||
inputField = TextField(
|
||||
renderWindow = hudRenderer.renderWindow,
|
||||
properties = TextFieldProperties(
|
||||
maxLength = 256,
|
||||
submitCloses = true,
|
||||
onSubmit = { hudRenderer.renderWindow.connection.sender.sendChatMessage(it) },
|
||||
onClose = { closeChat() },
|
||||
),
|
||||
)
|
||||
|
||||
layout.addChild(Vec2i(0, 0), inputField)
|
||||
inputField.apply()
|
||||
|
||||
hudRenderer.renderWindow.inputHandler.registerKeyCallback(KeyBindingsNames.OPEN_CHAT) {
|
||||
openChat()
|
||||
}
|
||||
hudRenderer.connection.registerEvent(CallbackEventInvoker.of<ScreenResizeEvent> {
|
||||
layout.sizing.minSize.x = it.screenDimensions.x
|
||||
layout.sizing.maxSize.x = it.screenDimensions.x
|
||||
inputField.textElement.setProperties.hardWrap = (inputField.textElement.sizing.minSize.x / scale).toInt()
|
||||
layout.apply()
|
||||
})
|
||||
}
|
||||
|
||||
fun openChat() {
|
||||
hudRenderer.renderWindow.inputHandler.currentKeyConsumer = inputField
|
||||
}
|
||||
|
||||
fun closeChat() {
|
||||
hudRenderer.renderWindow.inputHandler.currentKeyConsumer = null
|
||||
}
|
||||
|
||||
companion object : HUDRenderBuilder<ChatBoxHUDElement> {
|
||||
override val RESOURCE_LOCATION: ResourceLocation = ResourceLocation("minosoft:chat")
|
||||
override val DEFAULT_PROPERTIES = HUDElementProperties(
|
||||
position = Vec2(0.0f, -1.0f),
|
||||
xBinding = HUDElementProperties.PositionBindings.CENTER,
|
||||
)
|
||||
|
||||
override fun build(hudRenderer: HUDRenderer): ChatBoxHUDElement {
|
||||
return ChatBoxHUDElement(hudRenderer)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
/*
|
||||
* 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.nodes.debug
|
||||
|
||||
import de.bixilon.minosoft.data.text.ChatComponent
|
||||
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.HUDElement
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.layout.RowLayout
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.LabelNode
|
||||
|
||||
abstract class DebugScreenNode(hudRenderer: HUDRenderer) : HUDElement(hudRenderer) {
|
||||
override val layout = RowLayout(hudRenderer.renderWindow)
|
||||
protected var lastPrepareTime = 0L
|
||||
|
||||
fun text(text: String = ""): LabelNode {
|
||||
val textElement = LabelNode(hudRenderer.renderWindow, text = ChatComponent.of(text))
|
||||
layout.addRow(textElement)
|
||||
return textElement
|
||||
}
|
||||
}
|
@ -1,141 +0,0 @@
|
||||
/*
|
||||
* 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.nodes.debug
|
||||
|
||||
import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames
|
||||
import de.bixilon.minosoft.data.mappings.ResourceLocation
|
||||
import de.bixilon.minosoft.gui.rendering.hud.HUDElementProperties
|
||||
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderBuilder
|
||||
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.properties.NodeAlignment
|
||||
import de.bixilon.minosoft.gui.rendering.modding.events.ScreenResizeEvent
|
||||
import de.bixilon.minosoft.modding.event.CallbackEventInvoker
|
||||
import de.bixilon.minosoft.modding.loading.ModLoader
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||
import de.bixilon.minosoft.util.GitInfo
|
||||
import de.bixilon.minosoft.util.SystemInformation
|
||||
import de.bixilon.minosoft.util.UnitFormatter
|
||||
import glm_.vec2.Vec2
|
||||
import org.lwjgl.opengl.GL11.*
|
||||
|
||||
|
||||
class HUDSystemDebugNode(hudRenderer: HUDRenderer) : DebugScreenNode(hudRenderer) {
|
||||
|
||||
init {
|
||||
layout.sizing.forceAlign = NodeAlignment.RIGHT
|
||||
layout.sizing.padding.top = 2
|
||||
layout.sizing.padding.right = 2
|
||||
text("Java: ${Runtime.version()} ${System.getProperty("sun.arch.data.model")}bit")
|
||||
}
|
||||
|
||||
private val memoryText = text("TBA")
|
||||
private val allocatedMemoryText = text("TBA")
|
||||
|
||||
init {
|
||||
text("System: ${SystemInformation.SYSTEM_MEMORY_TEXT}")
|
||||
text()
|
||||
text("OS: ${SystemInformation.OS_TEXT}")
|
||||
text("CPU: ${SystemInformation.PROCESSOR_TEXT}")
|
||||
text()
|
||||
}
|
||||
|
||||
private val displayText = text("TBA")
|
||||
private val gpuText = text("TBA")
|
||||
private val gpuVersionText = text("TBA")
|
||||
|
||||
|
||||
init {
|
||||
text()
|
||||
text(
|
||||
if (GitInfo.IS_INITIALIZED) {
|
||||
"Commit: ${GitInfo.GIT_COMMIT_ID_DESCRIBE}: ${GitInfo.GIT_COMMIT_MESSAGE_SHORT}"
|
||||
} else {
|
||||
"GitInfo uninitialized :("
|
||||
})
|
||||
text()
|
||||
text("Mods: ${ModLoader.MOD_MAP.size} active, ${hudRenderer.connection.eventListenerSize} listeners")
|
||||
}
|
||||
|
||||
private val targetPosition = text("TBA")
|
||||
private val targetBlockState = text("TBA")
|
||||
|
||||
override fun init() {
|
||||
gpuText.sText = "GPU: " + (glGetString(GL_RENDERER) ?: "unknown")
|
||||
gpuVersionText.sText = "Version: " + (glGetString(GL_VERSION) ?: "unknown")
|
||||
|
||||
hudRenderer.connection.registerEvent(CallbackEventInvoker.of<ScreenResizeEvent> {
|
||||
displayText.sText = "Display: ${getScreenDimensions()}"
|
||||
})
|
||||
}
|
||||
|
||||
override fun draw() {
|
||||
if (System.currentTimeMillis() - lastPrepareTime < ProtocolDefinition.TICK_TIME * 2) {
|
||||
return
|
||||
}
|
||||
memoryText.sText = "Memory: ${getUsedMemoryPercent()}% ${getFormattedUsedMemory()}/${SystemInformation.MAX_MEMORY_TEXT}"
|
||||
allocatedMemoryText.sText = "Allocated: ${getAllocatedMemoryPercent()}% ${getFormattedAllocatedMemory()}"
|
||||
|
||||
val rayCastHit = hudRenderer.renderWindow.inputHandler.camera.getTargetBlock()
|
||||
if (rayCastHit == null) {
|
||||
targetPosition.sText = ""
|
||||
targetBlockState.sText = ""
|
||||
} else {
|
||||
targetPosition.sText = "Target block: ${rayCastHit.blockPosition}"
|
||||
targetBlockState.sText = rayCastHit.blockState.toString()
|
||||
}
|
||||
|
||||
lastPrepareTime = System.currentTimeMillis()
|
||||
}
|
||||
|
||||
private fun getUsedMemory(): Long {
|
||||
return SystemInformation.RUNTIME.totalMemory() - SystemInformation.RUNTIME.freeMemory()
|
||||
}
|
||||
|
||||
private fun getFormattedUsedMemory(): String {
|
||||
return UnitFormatter.formatBytes(getUsedMemory())
|
||||
}
|
||||
|
||||
private fun getAllocatedMemory(): Long {
|
||||
return SystemInformation.RUNTIME.totalMemory()
|
||||
}
|
||||
|
||||
private fun getFormattedAllocatedMemory(): String {
|
||||
return UnitFormatter.formatBytes(getAllocatedMemory())
|
||||
}
|
||||
|
||||
private fun getUsedMemoryPercent(): Long {
|
||||
return getUsedMemory() * 100 / SystemInformation.RUNTIME.maxMemory()
|
||||
}
|
||||
|
||||
private fun getAllocatedMemoryPercent(): Long {
|
||||
return getAllocatedMemory() * 100 / SystemInformation.RUNTIME.maxMemory()
|
||||
}
|
||||
|
||||
private fun getScreenDimensions(): String {
|
||||
return "${hudRenderer.renderWindow.screenDimensions.x}x${hudRenderer.renderWindow.screenDimensions.y}"
|
||||
}
|
||||
|
||||
companion object : HUDRenderBuilder<HUDSystemDebugNode> {
|
||||
override val RESOURCE_LOCATION: ResourceLocation = ResourceLocation("minosoft:system_debug_screen")
|
||||
override val DEFAULT_PROPERTIES = HUDElementProperties(
|
||||
position = Vec2(1.0f, 1.0f),
|
||||
toggleKeyBinding = KeyBindingsNames.TOGGLE_DEBUG_SCREEN,
|
||||
enabled = false,
|
||||
)
|
||||
|
||||
override fun build(hudRenderer: HUDRenderer): HUDSystemDebugNode {
|
||||
return HUDSystemDebugNode(hudRenderer)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,163 +0,0 @@
|
||||
/*
|
||||
* 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.nodes.debug
|
||||
|
||||
import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames
|
||||
import de.bixilon.minosoft.data.Directions
|
||||
import de.bixilon.minosoft.data.mappings.ResourceLocation
|
||||
import de.bixilon.minosoft.gui.rendering.chunk.WorldRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.hud.HUDElementProperties
|
||||
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderBuilder
|
||||
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.properties.NodeAlignment
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||
import de.bixilon.minosoft.util.UnitFormatter
|
||||
import glm_.vec2.Vec2
|
||||
import java.util.*
|
||||
|
||||
|
||||
class HUDWorldDebugNode(hudRenderer: HUDRenderer) : DebugScreenNode(hudRenderer) {
|
||||
private val camera = hudRenderer.renderWindow.inputHandler.camera
|
||||
private val worldRenderer = hudRenderer.renderWindow.rendererMap[WorldRenderer.RESOURCE_LOCATION] as WorldRenderer?
|
||||
|
||||
init {
|
||||
layout.sizing.forceAlign = NodeAlignment.LEFT
|
||||
layout.sizing.padding.left = 2
|
||||
layout.sizing.padding.top = 2
|
||||
text("§cMinosoft 0.1-pre1")
|
||||
}
|
||||
|
||||
private val fpsText = text("TBA")
|
||||
private val timingsText = text("TBA")
|
||||
private val chunksText = text("TBA")
|
||||
private val openGLText = text("TBA")
|
||||
|
||||
init {
|
||||
text("Connected to ${hudRenderer.connection.address} on ${hudRenderer.connection.version} with ${hudRenderer.connection.account.username}")
|
||||
text("")
|
||||
}
|
||||
|
||||
private val positionText = text("TBA")
|
||||
private val blockPositionText = text("TBA")
|
||||
private val chunkPositionText = text("TBA")
|
||||
private val facingText = text("TBA")
|
||||
private val gamemodeText = text("TBA")
|
||||
private val dimensionText = text("TBA")
|
||||
private val biomeText = text("TBA")
|
||||
|
||||
init {
|
||||
text()
|
||||
}
|
||||
|
||||
private val difficultyText = text("TBA")
|
||||
private val lightText = text("TBA")
|
||||
|
||||
|
||||
override fun draw() {
|
||||
if (System.currentTimeMillis() - lastPrepareTime < ProtocolDefinition.TICK_TIME * 2) {
|
||||
return
|
||||
}
|
||||
|
||||
fpsText.sText = "FPS: ${getFPS()}"
|
||||
chunksText.sText = "Chunks: q=${worldRenderer?.queuedChunks?.size} v=${worldRenderer?.visibleChunks?.size} p=${worldRenderer?.allChunkSections?.size} t=${hudRenderer.connection.world.chunks.size}"
|
||||
timingsText.sText = "Timings: avg ${getAvgFrameTime()}ms, min ${getMinFrameTime()}ms, max ${getMaxFrameTime()}ms"
|
||||
openGLText.sText = "GL: m=${worldRenderer?.meshes?.let { UnitFormatter.formatNumber(it) }} t=${worldRenderer?.triangles?.let { UnitFormatter.formatNumber(it) }}"
|
||||
|
||||
|
||||
// ToDo: Prepare on change
|
||||
gamemodeText.sText = "Gamemode: ${hudRenderer.connection.player.entity.gamemode.name.lowercase(Locale.getDefault())}"
|
||||
positionText.sText = "XYZ ${getPosition()}"
|
||||
blockPositionText.sText = "Block ${getBlockPosition()}"
|
||||
chunkPositionText.sText = "Chunk ${getChunkLocation()}"
|
||||
facingText.sText = "Facing: ${getFacing()}"
|
||||
|
||||
biomeText.sText = "Biome: ${camera.currentBiome}"
|
||||
dimensionText.sText = "Dimension: ${hudRenderer.connection.world.dimension}"
|
||||
|
||||
difficultyText.sText = "Difficulty: ${hudRenderer.connection.world.difficulty?.name?.lowercase(Locale.getDefault())}, ${
|
||||
if (hudRenderer.connection.world.difficultyLocked) {
|
||||
"locked"
|
||||
} else {
|
||||
"unlocked"
|
||||
}
|
||||
}"
|
||||
|
||||
lightText.sText = "Client light: sky=${hudRenderer.connection.world.worldLightAccessor.getSkyLight(camera.blockPosition)}, block=${hudRenderer.connection.world.worldLightAccessor.getBlockLight(camera.blockPosition)}"
|
||||
|
||||
|
||||
lastPrepareTime = System.currentTimeMillis()
|
||||
}
|
||||
|
||||
private fun nanoToMillis1d(nanos: Long): String {
|
||||
return "%.1f".format(nanos / 1E6f)
|
||||
}
|
||||
|
||||
private fun getFPS(): String {
|
||||
val renderStats = hudRenderer.renderWindow.renderStats
|
||||
return "${renderStats.fpsLastSecond}"
|
||||
}
|
||||
|
||||
private fun getAvgFrameTime(): String {
|
||||
return nanoToMillis1d(hudRenderer.renderWindow.renderStats.avgFrameTime)
|
||||
}
|
||||
|
||||
private fun getMinFrameTime(): String {
|
||||
return nanoToMillis1d(hudRenderer.renderWindow.renderStats.minFrameTime)
|
||||
}
|
||||
|
||||
private fun getMaxFrameTime(): String {
|
||||
return nanoToMillis1d(hudRenderer.renderWindow.renderStats.maxFrameTime)
|
||||
}
|
||||
|
||||
|
||||
private fun getPosition(): String {
|
||||
return "${formatCoordinate(camera.playerEntity.position.x)} / ${formatCoordinate(camera.playerEntity.position.y)} / ${formatCoordinate(camera.playerEntity.position.z)}"
|
||||
}
|
||||
|
||||
private fun getBlockPosition(): String {
|
||||
return "${camera.blockPosition.x} / ${camera.blockPosition.y} / ${camera.blockPosition.z}"
|
||||
}
|
||||
|
||||
private fun getChunkLocation(): String {
|
||||
return "${camera.inChunkSectionPosition.x} ${camera.inChunkSectionPosition.y} ${camera.inChunkSectionPosition.z} in ${camera.chunkPosition.x} ${camera.sectionHeight} ${camera.chunkPosition.y}"
|
||||
}
|
||||
|
||||
private fun getFacing(): String {
|
||||
val yaw = hudRenderer.renderWindow.inputHandler.camera.playerEntity.rotation.yaw
|
||||
val pitch = hudRenderer.renderWindow.inputHandler.camera.playerEntity.rotation.pitch
|
||||
val direction = Directions.byDirection(camera.cameraFront)
|
||||
return "${Directions.byDirection(camera.cameraFront).name.lowercase(Locale.getDefault())} ${direction.directionVector} (${formatRotation(yaw.toDouble())} / ${formatRotation(pitch.toDouble())})"
|
||||
}
|
||||
|
||||
companion object : HUDRenderBuilder<HUDWorldDebugNode> {
|
||||
override val RESOURCE_LOCATION: ResourceLocation = ResourceLocation("minosoft:world_debug_screen")
|
||||
override val DEFAULT_PROPERTIES = HUDElementProperties(
|
||||
position = Vec2(-1.0f, 1.0f),
|
||||
toggleKeyBinding = KeyBindingsNames.TOGGLE_DEBUG_SCREEN,
|
||||
enabled = false,
|
||||
)
|
||||
|
||||
override fun build(hudRenderer: HUDRenderer): HUDWorldDebugNode {
|
||||
return HUDWorldDebugNode(hudRenderer)
|
||||
}
|
||||
|
||||
fun formatCoordinate(coordinate: Float): String {
|
||||
return "%.3f".format(coordinate)
|
||||
}
|
||||
|
||||
fun formatRotation(rotation: Double): String {
|
||||
return "%.1f".format(rotation)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,139 +0,0 @@
|
||||
/*
|
||||
* 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.nodes.layout
|
||||
|
||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.Node
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.properties.NodeAlignment
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.properties.NodeSizing
|
||||
import de.bixilon.minosoft.util.KUtil.synchronizedMapOf
|
||||
import de.bixilon.minosoft.util.KUtil.toSynchronizedMap
|
||||
import de.bixilon.minosoft.util.MMath
|
||||
import glm_.mat4x4.Mat4
|
||||
import glm_.vec2.Vec2i
|
||||
|
||||
open class AbsoluteLayout(
|
||||
renderWindow: RenderWindow,
|
||||
sizing: NodeSizing = NodeSizing(),
|
||||
initialCacheSize: Int = DEFAULT_INITIAL_CACHE_SIZE,
|
||||
) : Layout(renderWindow, sizing, initialCacheSize) {
|
||||
private val children: MutableMap<Node, Vec2i> = synchronizedMapOf()
|
||||
|
||||
override fun clearChildren() {
|
||||
children.clear()
|
||||
}
|
||||
|
||||
fun addChild(start: Vec2i, child: Node) {
|
||||
child.parent = this
|
||||
child.apply()
|
||||
if (children.isEmpty()) {
|
||||
start.x += child.sizing.margin.left + sizing.padding.left
|
||||
start.y += child.sizing.margin.top + sizing.padding.top
|
||||
}
|
||||
children[child] = start
|
||||
apply()
|
||||
}
|
||||
|
||||
override fun recursiveApply() {
|
||||
for ((child, _) in children.toSynchronizedMap()) {
|
||||
if (child is AbsoluteLayout) {
|
||||
child.recursiveApply()
|
||||
} else {
|
||||
child.apply()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun checkAlignment() {
|
||||
when (sizing.forceAlign) {
|
||||
NodeAlignment.RIGHT -> {
|
||||
for ((child, start) in children.toSynchronizedMap()) {
|
||||
start.x = sizing.currentSize.x - (child.sizing.margin.right + sizing.padding.right + child.sizing.currentSize.x)
|
||||
}
|
||||
}
|
||||
NodeAlignment.LEFT -> {
|
||||
for ((child, start) in children.toSynchronizedMap()) {
|
||||
start.x = child.sizing.margin.left + sizing.padding.left
|
||||
}
|
||||
}
|
||||
NodeAlignment.CENTER -> {
|
||||
for ((child, start) in children.toSynchronizedMap()) {
|
||||
start.x = (sizing.currentSize.x - child.sizing.currentSize.x) / 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun apply() {
|
||||
sizing.validate()
|
||||
clearCache()
|
||||
recalculateSize()
|
||||
checkAlignment()
|
||||
parent?.apply()
|
||||
}
|
||||
|
||||
override fun recalculateSize() {
|
||||
sizing.currentSize = Vec2i(sizing.minSize)
|
||||
for ((childNode, start) in children.toSynchronizedMap()) {
|
||||
checkSize(childNode, start)
|
||||
}
|
||||
}
|
||||
|
||||
override fun clearCache() {
|
||||
cache.clear()
|
||||
parent?.clearCache()
|
||||
}
|
||||
|
||||
private fun checkSize(child: Node, start: Vec2i) {
|
||||
var changed = false
|
||||
val end = start + child.sizing.currentSize
|
||||
if (end.x > sizing.currentSize.x) {
|
||||
sizing.currentSize.x = MMath.clamp(end.x, sizing.minSize.x, sizing.maxSize.x)
|
||||
changed = true
|
||||
}
|
||||
if (end.y > sizing.currentSize.y) {
|
||||
sizing.currentSize.y = MMath.clamp(end.y, sizing.minSize.y, sizing.maxSize.y)
|
||||
changed = true
|
||||
}
|
||||
if (changed) {
|
||||
clearCache()
|
||||
}
|
||||
}
|
||||
|
||||
private fun addToStart(start: Vec2i, elementPosition: Vec2i): Vec2i {
|
||||
return Vec2i(start.x + elementPosition.x, start.y - elementPosition.y)
|
||||
}
|
||||
|
||||
override fun prepareCache(start: Vec2i, scaleFactor: Float, matrix: Mat4, z: Int) {
|
||||
for ((child, childStart) in children.toSynchronizedMap()) {
|
||||
child.checkCache(addToStart(start, childStart * scaleFactor), scaleFactor, matrix, z)
|
||||
cache.addCache(child.cache)
|
||||
}
|
||||
}
|
||||
|
||||
override fun clearChildrenCache() {
|
||||
for ((child, _) in children.toSynchronizedMap()) {
|
||||
if (child is AbsoluteLayout) {
|
||||
child.clearChildrenCache()
|
||||
} else {
|
||||
child.clearCache()
|
||||
}
|
||||
}
|
||||
clearCache()
|
||||
}
|
||||
|
||||
override fun removeChild(node: Node) {
|
||||
children.remove(node)
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
/*
|
||||
* 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.nodes.layout
|
||||
|
||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.Node
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.properties.NodeSizing
|
||||
|
||||
abstract class Layout(
|
||||
renderWindow: RenderWindow,
|
||||
sizing: NodeSizing = NodeSizing(),
|
||||
initialCacheSize: Int = DEFAULT_INITIAL_CACHE_SIZE,
|
||||
) : Node(renderWindow, sizing, initialCacheSize) {
|
||||
|
||||
abstract fun clearChildren()
|
||||
|
||||
abstract fun recursiveApply()
|
||||
|
||||
abstract fun checkAlignment()
|
||||
|
||||
abstract fun recalculateSize()
|
||||
|
||||
abstract fun clearChildrenCache()
|
||||
|
||||
abstract fun removeChild(node: Node)
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
/*
|
||||
* 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.nodes.layout
|
||||
|
||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.Node
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.properties.NodeSizing
|
||||
import glm_.vec2.Vec2i
|
||||
|
||||
class RowLayout(
|
||||
renderWindow: RenderWindow,
|
||||
sizing: NodeSizing = NodeSizing(),
|
||||
initialCacheSize: Int = DEFAULT_INITIAL_CACHE_SIZE,
|
||||
) : AbsoluteLayout(renderWindow, sizing, initialCacheSize) {
|
||||
|
||||
fun addRow(node: Node) {
|
||||
addChild(Vec2i(0, sizing.currentSize.y + node.sizing.margin.top + node.sizing.padding.top), node)
|
||||
apply()
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package de.bixilon.minosoft.gui.rendering.hud.nodes.position
|
||||
|
||||
import de.bixilon.minosoft.data.mappings.ResourceLocation
|
||||
import glm_.vec2.Vec2i
|
||||
|
||||
enum class HUDElementPositionAnchors(val resourceLocation: ResourceLocation, val quadTransform: (Vec2i, Vec2i) -> Array<Vec2i>) {
|
||||
CENTER(ResourceLocation("minosoft:center"), { position, size ->
|
||||
arrayOf(
|
||||
Vec2i(position.x + size.x * 0.5f, position.y + size.y * 0.5f),
|
||||
Vec2i(position.x + size.x * 0.5f, position.y - size.y * 0.5f),
|
||||
Vec2i(position.x - size.x * 0.5f, position.y + size.y * 0.5f),
|
||||
Vec2i(position.x - size.x * 0.5f, position.y - size.y * 0.5f),
|
||||
)
|
||||
})
|
||||
;
|
||||
companion object {
|
||||
val HUD_ELEMENT_POSITION_ATTACHMENT_OPTIONS = values()
|
||||
|
||||
val HUD_ELEMENT_POSITION_ATTACHMENTS_MAPPING = run {
|
||||
val result = mutableMapOf<ResourceLocation, HUDElementPositionAnchors>()
|
||||
for (hudPositionAttachmentOption in HUD_ELEMENT_POSITION_ATTACHMENT_OPTIONS) {
|
||||
result[hudPositionAttachmentOption.resourceLocation] = hudPositionAttachmentOption
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package de.bixilon.minosoft.gui.rendering.hud.nodes.position
|
||||
|
||||
import de.bixilon.minosoft.Minosoft
|
||||
import de.bixilon.minosoft.data.Axes
|
||||
import de.bixilon.minosoft.data.mappings.ResourceLocation
|
||||
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil.get
|
||||
|
||||
enum class HUDElementPositionUnits(val resourceLocation: ResourceLocation, val realPositionConversion: (Float, HUDRenderer, Axes) -> Float) {
|
||||
PIXELS(ResourceLocation("minosoft:pixel"), { it, _, _ ->
|
||||
it
|
||||
}),
|
||||
SCALED_PIXELS(ResourceLocation("minosoft:scaled_pixel"), { it, _, _ ->
|
||||
it * Minosoft.getConfig().config.game.hud.scale
|
||||
}),
|
||||
UNIT(ResourceLocation("minosoft:unit"), { it, hudRenderer, axis ->
|
||||
it * hudRenderer.renderWindow.screenDimensions[axis] / TOTAL_UNITS
|
||||
}),
|
||||
SCALED_UNIT(ResourceLocation("minosoft:scaled_unit"), { it, hudRenderer, axis ->
|
||||
it * hudRenderer.renderWindow.screenDimensions[axis] / TOTAL_UNITS * Minosoft.getConfig().config.game.hud.scale
|
||||
})
|
||||
;
|
||||
|
||||
companion object {
|
||||
val HUD_ELEMENT_POSITION_UNITS = values()
|
||||
|
||||
val HUD_ELEMENT_POSITION_MAP = run {
|
||||
val result = mutableMapOf<ResourceLocation, HUDElementPositionUnits>()
|
||||
for (unit in HUD_ELEMENT_POSITION_UNITS) {
|
||||
result[unit.resourceLocation] = unit
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
const val TOTAL_UNITS = 100f
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package de.bixilon.minosoft.gui.rendering.hud.nodes.position
|
||||
|
||||
import de.bixilon.minosoft.data.Axes
|
||||
import de.bixilon.minosoft.data.mappings.ResourceLocation
|
||||
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
|
||||
import glm_.vec2.Vec2i
|
||||
|
||||
class HUDElementVec2(
|
||||
val x: Float,
|
||||
val xUnit: HUDElementPositionUnits,
|
||||
val y: Float,
|
||||
val yUnit: HUDElementPositionUnits,
|
||||
) {
|
||||
fun getRealVector(hudRenderer: HUDRenderer): Vec2i {
|
||||
return Vec2i(
|
||||
xUnit.realPositionConversion.invoke(x, hudRenderer, Axes.X),
|
||||
yUnit.realPositionConversion.invoke(y, hudRenderer, Axes.Y)
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun deserialize(data: Any?): HUDElementVec2? {
|
||||
if (data !is Map<*, *>) {
|
||||
return null
|
||||
}
|
||||
val x = (data["x"] as Double).toFloat()
|
||||
val xUnit = HUDElementPositionUnits.HUD_ELEMENT_POSITION_MAP[ResourceLocation(data["x_unit"].toString())] ?: HUDElementPositionUnits.PIXELS
|
||||
val y = (data["x"] as Double).toFloat()
|
||||
val yUnit = HUDElementPositionUnits.HUD_ELEMENT_POSITION_MAP[ResourceLocation(data["y_unit"].toString())] ?: HUDElementPositionUnits.PIXELS
|
||||
return HUDElementVec2(x, xUnit, y, yUnit)
|
||||
}
|
||||
}
|
||||
}
|
@ -11,22 +11,32 @@
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.gui.rendering.hud.nodes
|
||||
package de.bixilon.minosoft.gui.rendering.hud.nodes.primitive
|
||||
|
||||
import de.bixilon.minosoft.Minosoft
|
||||
import de.bixilon.minosoft.gui.rendering.hud.HUDElementProperties
|
||||
import de.bixilon.minosoft.data.mappings.ResourceLocation
|
||||
import de.bixilon.minosoft.data.text.RGBColor
|
||||
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.layout.Layout
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.position.HUDElementPositionAnchors
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.position.HUDElementVec2
|
||||
import glm_.mat4x4.Mat4
|
||||
|
||||
abstract class HUDElement(protected val hudRenderer: HUDRenderer) {
|
||||
abstract val layout: Layout
|
||||
abstract class HUDElement(
|
||||
val position: HUDElementVec2,
|
||||
val positionAnchor: HUDElementPositionAnchors,
|
||||
val content: ResourceLocation,
|
||||
val size: HUDElementVec2,
|
||||
val realZ: Float,
|
||||
val tint: RGBColor,
|
||||
) {
|
||||
lateinit var hudRenderer: HUDRenderer
|
||||
|
||||
lateinit var properties: HUDElementProperties
|
||||
open fun init(hudRenderer: HUDRenderer) {
|
||||
this.hudRenderer = hudRenderer
|
||||
}
|
||||
|
||||
val scale: Float
|
||||
get() = properties.scale * Minosoft.getConfig().config.game.hud.scale
|
||||
|
||||
open fun init() {}
|
||||
open fun postInit() {}
|
||||
|
||||
open fun draw() {}
|
||||
|
||||
open fun prepare(matrix: Mat4) {}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package de.bixilon.minosoft.gui.rendering.hud.nodes.primitive
|
||||
|
||||
import com.squareup.moshi.FromJson
|
||||
import com.squareup.moshi.JsonWriter
|
||||
import com.squareup.moshi.ToJson
|
||||
import de.bixilon.minosoft.data.mappings.ResourceLocation
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.position.HUDElementPositionAnchors
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.position.HUDElementVec2
|
||||
import de.bixilon.minosoft.util.json.RGBColorSerializer
|
||||
|
||||
object HUDElementSerializer {
|
||||
@FromJson
|
||||
fun fromJson(json: Map<String, Any>): HUDElement? {
|
||||
val position = HUDElementVec2.deserialize(json["position"])
|
||||
val positionAnchor = HUDElementPositionAnchors.HUD_ELEMENT_POSITION_ATTACHMENTS_MAPPING[ResourceLocation((json["position"] as Map<*,*>)["location"].toString())]!!
|
||||
val size = HUDElementVec2.deserialize(json["size"])
|
||||
return HUD_ELEMENT_TYPES[ResourceLocation(json["type"].toString())]?.constructors?.first()?.call(
|
||||
position,
|
||||
positionAnchor,
|
||||
ResourceLocation(json["content"].toString()),
|
||||
size,
|
||||
(json["real_z"] as Double).toFloat(),
|
||||
json["tint"]?.let{ RGBColorSerializer.fromJsonValue(it) },
|
||||
)
|
||||
}
|
||||
|
||||
@ToJson
|
||||
fun toJson(jsonWriter: JsonWriter, hudElement: HUDElement?) {
|
||||
}
|
||||
|
||||
private val HUD_ELEMENT_TYPES = mutableMapOf(
|
||||
ResourceLocation("minosoft:image_element") to HUDImageElement::class,
|
||||
// modding here!
|
||||
)
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
package de.bixilon.minosoft.gui.rendering.hud.nodes.primitive
|
||||
|
||||
import de.bixilon.minosoft.data.mappings.ResourceLocation
|
||||
import de.bixilon.minosoft.data.text.ChatColors
|
||||
import de.bixilon.minosoft.data.text.RGBColor
|
||||
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.hud.atlas.HUDAtlasElement
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.position.HUDElementPositionAnchors
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.position.HUDElementVec2
|
||||
import de.bixilon.minosoft.gui.rendering.util.mesh.Mesh
|
||||
import de.bixilon.minosoft.gui.rendering.util.mesh.SimpleTextureMesh
|
||||
import glm_.mat4x4.Mat4
|
||||
import glm_.vec2.Vec2
|
||||
import glm_.vec3.Vec3
|
||||
import glm_.vec4.Vec4
|
||||
import glm_.vec4.swizzle.xy
|
||||
|
||||
class HUDImageElement(
|
||||
position: HUDElementVec2,
|
||||
positionAnchor: HUDElementPositionAnchors,
|
||||
content: ResourceLocation,
|
||||
size: HUDElementVec2,
|
||||
realZ: Float,
|
||||
tint: RGBColor = ChatColors.WHITE,
|
||||
) : HUDElement(position, positionAnchor, content, size, realZ, tint) {
|
||||
|
||||
private var mesh = SimpleTextureMesh()
|
||||
|
||||
private lateinit var hudAtlasElement: HUDAtlasElement
|
||||
|
||||
override fun init(hudRenderer: HUDRenderer) {
|
||||
super.init(hudRenderer)
|
||||
hudAtlasElement = hudRenderer.hudAtlasElements[content]!!
|
||||
}
|
||||
|
||||
override fun draw() {
|
||||
mesh.draw()
|
||||
}
|
||||
|
||||
override fun prepare(matrix: Mat4) {
|
||||
super.prepare(matrix)
|
||||
if (mesh.state == Mesh.MeshStates.LOADED) {
|
||||
mesh.unload()
|
||||
mesh = SimpleTextureMesh()
|
||||
}
|
||||
val realPosition = position.getRealVector(hudRenderer)
|
||||
val realSize = size.getRealVector(hudRenderer)
|
||||
fun addVertex(position: Vec2, textureUV: Vec2) {
|
||||
mesh.addVertex(Vec3(
|
||||
position.x,
|
||||
position.y,
|
||||
realZ,
|
||||
), hudAtlasElement.texture, textureUV, tint)
|
||||
}
|
||||
val positions = positionAnchor.quadTransform.invoke(realPosition, realSize)
|
||||
val uvs = hudAtlasElement.uvs
|
||||
for (position in arrayOf(0, 1, 2, 1, 3, 2)) {
|
||||
addVertex((matrix * Vec4(positions[position], 1f, 1f)).xy, uvs[position])
|
||||
}
|
||||
mesh.load()
|
||||
}
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
/*
|
||||
* 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.nodes.primitive
|
||||
|
||||
import de.bixilon.minosoft.data.text.RGBColor
|
||||
import de.bixilon.minosoft.gui.rendering.RenderConstants
|
||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||
import de.bixilon.minosoft.gui.rendering.hud.atlas.TextureLike
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.properties.NodeSizing
|
||||
import de.bixilon.minosoft.gui.rendering.util.mesh.SimpleTextureMesh
|
||||
import glm_.mat4x4.Mat4
|
||||
import glm_.vec2.Vec2
|
||||
import glm_.vec2.Vec2i
|
||||
import glm_.vec3.Vec3
|
||||
import glm_.vec4.Vec4
|
||||
|
||||
class ImageNode(
|
||||
renderWindow: RenderWindow,
|
||||
sizing: NodeSizing = NodeSizing(),
|
||||
var textureLike: TextureLike?,
|
||||
val z: Int = 0,
|
||||
val tintColor: RGBColor? = null,
|
||||
) : Node(renderWindow, sizing = sizing, initialCacheSize = SimpleTextureMesh.SimpleTextureMeshStruct.FLOATS_PER_VERTEX * 6) {
|
||||
|
||||
private fun addToStart(start: Vec2i, elementPosition: Vec2i): Vec2i {
|
||||
return Vec2i(start.x + elementPosition.x, start.y - elementPosition.y)
|
||||
}
|
||||
|
||||
private fun addToEnd(start: Vec2i, elementPosition: Vec2i): Vec2i {
|
||||
return Vec2i(start.x + elementPosition.x, start.y - elementPosition.y)
|
||||
}
|
||||
|
||||
override fun apply() {}
|
||||
|
||||
override fun prepareCache(start: Vec2i, scaleFactor: Float, matrix: Mat4, z: Int) {
|
||||
val modelStart = matrix * Vec4(RenderConstants.PIXEL_UV_PIXEL_ADD + start, 1.0f, 1.0f)
|
||||
val ourEnd = addToEnd(start, sizing.currentSize * scaleFactor)
|
||||
val modelEnd = matrix * Vec4(RenderConstants.PIXEL_UV_PIXEL_ADD + ourEnd, 1.0f, 1.0f)
|
||||
|
||||
val uvStart = textureLike?.uvStart ?: Vec2()
|
||||
val uvEnd = textureLike?.uvEnd ?: Vec2()
|
||||
|
||||
val realZ = RenderConstants.HUD_Z_COORDINATE + RenderConstants.HUD_Z_COORDINATE_Z_FACTOR * (this.z + z)
|
||||
|
||||
fun addVertex(positionX: Float, positionY: Float, textureUV: Vec2) {
|
||||
cache.addVertex(Vec3(positionX, positionY, realZ), textureUV, textureLike?.texture, tintColor)
|
||||
}
|
||||
|
||||
addVertex(modelStart.x, modelStart.y, Vec2(uvStart.x, uvStart.y))
|
||||
addVertex(modelStart.x, modelEnd.y, Vec2(uvStart.x, uvEnd.y))
|
||||
addVertex(modelEnd.x, modelStart.y, Vec2(uvEnd.x, uvStart.y))
|
||||
addVertex(modelStart.x, modelEnd.y, Vec2(uvStart.x, uvEnd.y))
|
||||
addVertex(modelEnd.x, modelEnd.y, Vec2(uvEnd.x, uvEnd.y))
|
||||
addVertex(modelEnd.x, modelStart.y, Vec2(uvEnd.x, uvStart.y))
|
||||
}
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
/*
|
||||
* 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.nodes.primitive
|
||||
|
||||
import de.bixilon.minosoft.data.text.ChatComponent
|
||||
import de.bixilon.minosoft.data.text.RGBColor
|
||||
import de.bixilon.minosoft.gui.rendering.RenderConstants
|
||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||
import de.bixilon.minosoft.gui.rendering.font.Font
|
||||
import de.bixilon.minosoft.gui.rendering.font.text.TextGetProperties
|
||||
import de.bixilon.minosoft.gui.rendering.font.text.TextSetProperties
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.layout.AbsoluteLayout
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.properties.NodeSizing
|
||||
import glm_.vec2.Vec2i
|
||||
|
||||
class LabelNode(
|
||||
renderWindow: RenderWindow,
|
||||
sizing: NodeSizing = NodeSizing(minSize = Vec2i(0, Font.CHAR_HEIGHT + 2 * TEXT_BACKGROUND_OFFSET)),
|
||||
text: ChatComponent = ChatComponent.of(""),
|
||||
var background: Boolean = true,
|
||||
val setProperties: TextSetProperties = TextSetProperties(),
|
||||
) : AbsoluteLayout(renderWindow, sizing) {
|
||||
var getProperties = TextGetProperties()
|
||||
private set
|
||||
|
||||
var text: ChatComponent = text
|
||||
set(value) {
|
||||
field = value
|
||||
prepare()
|
||||
}
|
||||
|
||||
var sText: String
|
||||
get() = text.message
|
||||
set(value) {
|
||||
text = ChatComponent.of(value)
|
||||
}
|
||||
|
||||
init {
|
||||
prepare()
|
||||
}
|
||||
|
||||
private fun prepare() {
|
||||
clearChildren()
|
||||
getProperties = TextGetProperties()
|
||||
val textStartPosition = Vec2i(TEXT_BACKGROUND_OFFSET, TEXT_BACKGROUND_OFFSET)
|
||||
text.prepareRender(textStartPosition, Vec2i(), renderWindow, this, 1, setProperties, getProperties)
|
||||
|
||||
if (background && text.message.isNotBlank()) {
|
||||
drawBackground(getProperties.size + textStartPosition + TEXT_BACKGROUND_OFFSET)
|
||||
}
|
||||
apply()
|
||||
}
|
||||
|
||||
private fun drawBackground(end: Vec2i, z: Int = 1, tintColor: RGBColor = RenderConstants.TEXT_BACKGROUND_COLOR) {
|
||||
addChild(Vec2i(0, 0), ImageNode(renderWindow, NodeSizing(minSize = end), renderWindow.WHITE_TEXTURE, 0, tintColor))
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TEXT_BACKGROUND_OFFSET = 1
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
/*
|
||||
* 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.nodes.primitive
|
||||
|
||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||
import de.bixilon.minosoft.gui.rendering.hud.HUDCacheMesh
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.properties.NodeSizing
|
||||
import glm_.mat4x4.Mat4
|
||||
import glm_.vec2.Vec2i
|
||||
|
||||
abstract class Node(
|
||||
val renderWindow: RenderWindow,
|
||||
val sizing: NodeSizing = NodeSizing(),
|
||||
initialCacheSize: Int = DEFAULT_INITIAL_CACHE_SIZE,
|
||||
) {
|
||||
val cache = HUDCacheMesh(initialCacheSize)
|
||||
open var parent: Node? = null
|
||||
|
||||
abstract fun apply()
|
||||
|
||||
fun needsCacheUpdate(): Boolean {
|
||||
return cache.isEmpty()
|
||||
}
|
||||
|
||||
fun checkCache(start: Vec2i, scaleFactor: Float, matrix: Mat4, z: Int = 1) {
|
||||
if (!needsCacheUpdate()) {
|
||||
return
|
||||
}
|
||||
prepareCache(start, scaleFactor, matrix, z)
|
||||
}
|
||||
|
||||
open fun clearCache() {
|
||||
cache.clear()
|
||||
}
|
||||
|
||||
abstract fun prepareCache(start: Vec2i, scaleFactor: Float, matrix: Mat4, z: Int = 1)
|
||||
|
||||
companion object {
|
||||
const val DEFAULT_INITIAL_CACHE_SIZE = 1000
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
/*
|
||||
* 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.nodes.properties
|
||||
|
||||
enum class NodeAlignment {
|
||||
LEFT,
|
||||
RIGHT,
|
||||
CENTER,
|
||||
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* 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.nodes.properties
|
||||
|
||||
import de.bixilon.minosoft.util.MMath
|
||||
import glm_.vec2.Vec2i
|
||||
|
||||
data class NodeSizing(
|
||||
var minSize: Vec2i = Vec2i(0, 0),
|
||||
var maxSize: Vec2i = Vec2i(Int.MAX_VALUE, Int.MAX_VALUE),
|
||||
var margin: Spacing = Spacing(0, 0, 0, 0),
|
||||
var padding: Spacing = Spacing(0, 0, 0, 0),
|
||||
var forceAlign: NodeAlignment? = null,
|
||||
) {
|
||||
var currentSize: Vec2i = Vec2i(minSize)
|
||||
|
||||
|
||||
fun validate() {
|
||||
MMath.clamp(currentSize, minSize, maxSize)
|
||||
}
|
||||
|
||||
var forceSize: Vec2i
|
||||
get() = currentSize
|
||||
set(value) {
|
||||
minSize = value
|
||||
maxSize = value
|
||||
validate()
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
/*
|
||||
* 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.nodes.properties
|
||||
|
||||
data class Spacing(
|
||||
var top: Int = 0,
|
||||
var right: Int = 0,
|
||||
var bottom: Int = 0,
|
||||
var left: Int = 0,
|
||||
)
|
@ -328,4 +328,20 @@ object VecUtil {
|
||||
Axes.Z -> this.z
|
||||
}
|
||||
}
|
||||
|
||||
operator fun Vec2i.get(axis: Axes): Int {
|
||||
return when (axis) {
|
||||
Axes.X -> this.x
|
||||
Axes.Y -> this.y
|
||||
Axes.Z -> throw java.lang.IllegalArgumentException("Z does not exist")
|
||||
}
|
||||
}
|
||||
|
||||
operator fun Vec2.get(axis: Axes): Float {
|
||||
return when (axis) {
|
||||
Axes.X -> this.x
|
||||
Axes.Y -> this.y
|
||||
Axes.Z -> throw java.lang.IllegalArgumentException("Z does not exist")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ import com.squareup.moshi.Moshi
|
||||
import com.squareup.moshi.Types
|
||||
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
|
||||
import de.bixilon.minosoft.config.config.Config
|
||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.HUDElementSerializer
|
||||
import de.bixilon.minosoft.gui.rendering.textures.properties.ImageProperties
|
||||
|
||||
object JSONSerializer {
|
||||
@ -27,6 +28,7 @@ object JSONSerializer {
|
||||
.add(AccountSerializer)
|
||||
.add(ServerSerializer)
|
||||
.add(ResourceLocationSerializer)
|
||||
.add(HUDElementSerializer)
|
||||
.add(KotlinJsonAdapterFactory())
|
||||
.build()!!
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user