diff --git a/src/main/java/de/bixilon/minosoft/data/entities/entities/Entity.kt b/src/main/java/de/bixilon/minosoft/data/entities/entities/Entity.kt index a164733aa..b83ed1ded 100644 --- a/src/main/java/de/bixilon/minosoft/data/entities/entities/Entity.kt +++ b/src/main/java/de/bixilon/minosoft/data/entities/entities/Entity.kt @@ -49,12 +49,12 @@ abstract class Entity( protected open val hasCollisions = true private val defaultAABB = AABB( - Vec3(-(entityType.width / 2 + HITBOX_MARGIN), 0 , -(entityType.width / 2 + HITBOX_MARGIN)), - Vec3(+(entityType.width / 2 + HITBOX_MARGIN), entityType.height , +(entityType.width / 2 + HITBOX_MARGIN)) + Vec3(-(entityType.width / 2 + HITBOX_MARGIN), 0, -(entityType.width / 2 + HITBOX_MARGIN)), + Vec3(+(entityType.width / 2 + HITBOX_MARGIN), entityType.height, +(entityType.width / 2 + HITBOX_MARGIN)) ) - fun forceMove(relativePosition: Vec3) { - position = position + relativePosition + fun forceMove(deltaPosition: Vec3) { + position = position + deltaPosition } fun addEffect(effect: StatusEffectInstance) { @@ -202,6 +202,7 @@ abstract class Entity( val blockPositions = (originalAABB extend deltaPosition extend Directions.DOWN.directionVector).getBlockPositions() val result = VoxelShape() for (blockPosition in blockPositions) { + // ToDo: Check if chunk is loaded val blockState = connection.world.getBlockState(blockPosition) ?: continue result.add(blockState.collisionShape + blockPosition) } 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 bbd42a69d..53be6eca3 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 @@ -23,11 +23,13 @@ import de.bixilon.minosoft.gui.rendering.Renderer import de.bixilon.minosoft.gui.rendering.hud.atlas.HUDAtlasElement 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.shader.Shader 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 @@ -87,6 +89,11 @@ class HUDRenderer(val connection: PlayConnection, val renderWindow: RenderWindow toggleKeyBinding = KeyBindingsNames.TOGGLE_DEBUG_SCREEN, enabled = false, )) + addElement(ElementsNames.CHAT_RESOURCE_LOCATION, ChatBoxHUDElement(this), HUDElementProperties( + position = Vec2(0.0f, -1.0f), + xBinding = HUDElementProperties.PositionBindings.CENTER, + )) + } fun addElement(resourceLocation: ResourceLocation, hudElement: HUDElement, defaultProperties: HUDElementProperties) { @@ -174,6 +181,8 @@ class HUDRenderer(val connection: PlayConnection, val renderWindow: RenderWindow 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) diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/input/SubmittableTextField.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/input/SubmittableTextField.kt new file mode 100644 index 000000000..76be81558 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/input/SubmittableTextField.kt @@ -0,0 +1,40 @@ +/* + * 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.input + +import de.bixilon.minosoft.config.key.KeyCodes +import de.bixilon.minosoft.gui.rendering.RenderWindow + +class SubmittableTextField( + renderWindow: RenderWindow, + defaultText: String = "", + maxLength: Int = 256, + private val onSubmit: (text: String) -> Unit, +) : TextField(renderWindow, defaultText, maxLength) { + + fun submit() { + onSubmit.invoke(text) + text = "" + } + + + override fun keyInput(keyCodes: KeyCodes) { + if (keyCodes == KeyCodes.KEY_ENTER) { + // submit + submit() + return + } + super.keyInput(keyCodes) + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/input/TextField.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/input/TextField.kt new file mode 100644 index 000000000..9f2ec480e --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/input/TextField.kt @@ -0,0 +1,104 @@ +/* + * 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.input + +import de.bixilon.minosoft.config.key.KeyCodes +import de.bixilon.minosoft.data.text.ChatComponent +import de.bixilon.minosoft.gui.rendering.RenderConstants +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.ImageNode +import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.LabelNode +import de.bixilon.minosoft.util.MMath +import glm_.vec2.Vec2i + + +open class TextField( + renderWindow: RenderWindow, + defaultText: String = "", + var maxLength: Int = 256, +) : AbsoluteLayout(renderWindow), KeyConsumer, MouseConsumer { + override var focused: Boolean = true + private var textBuilder: StringBuilder = StringBuilder(defaultText) + private val textElement = LabelNode(renderWindow, sizing = sizing, text = ChatComponent.valueOf(raw = text), background = false) + 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) + addChild(Vec2i(0, 0), ImageNode(renderWindow, sizing = sizing, renderWindow.WHITE_TEXTURE, 0, RenderConstants.TEXT_BACKGROUND_COLOR)) + clearChildrenCache() + } + + fun clearText() { + textBuilder.clear() + update() + } + + private fun update() { + textElement.text = ChatComponent.valueOf(raw = text) + } + + override fun keyInput(keyCodes: KeyCodes) { + when (keyCodes) { + KeyCodes.KEY_BACKSPACE -> { + if (textBuilder.isEmpty()) { + return + } + textBuilder.deleteCharAt(--position) + } + KeyCodes.KEY_DELETE -> { + if (textBuilder.isEmpty() || position == textBuilder.length) { + return + } + textBuilder.deleteCharAt(position) + } + KeyCodes.KEY_ENTER -> { + if (position > maxLength) { + return + } + textBuilder.insert(position++, '\n') + } + KeyCodes.KEY_LEFT -> { + position = MMath.clamp(position - 1, 0, text.length) + return + } + KeyCodes.KEY_RIGHT -> { + position = MMath.clamp(position + 1, 0, text.length) + return + } + // ToDo: Up and down for line breaks, shift and ctrl modifier, ... + else -> { + return + } + } + update() + super.keyInput(keyCodes) + } + + override fun charInput(char: Char) { + if (position >= maxLength) { + return + } + textBuilder.insert(position++, char.toString()) + update() + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/nodes/chat/ChatBoxHUDElement.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/nodes/chat/ChatBoxHUDElement.kt new file mode 100644 index 000000000..b2db30217 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/nodes/chat/ChatBoxHUDElement.kt @@ -0,0 +1,62 @@ +/* + * 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.nodes.chat + + +import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames +import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer +import de.bixilon.minosoft.gui.rendering.hud.elements.input.SubmittableTextField +import de.bixilon.minosoft.gui.rendering.hud.nodes.HUDElement +import glm_.vec2.Vec2i + +class ChatBoxHUDElement(hudRenderer: HUDRenderer) : HUDElement(hudRenderer) { + private lateinit var inputField: SubmittableTextField + + override fun init() { + inputField = SubmittableTextField(renderWindow = hudRenderer.renderWindow, maxLength = 256, onSubmit = { + hudRenderer.renderWindow.connection.sender.sendChatMessage(it) + closeChat() + }) + + layout.addChild(Vec2i(0, 0), inputField) + inputField.apply() + + hudRenderer.renderWindow.registerKeyCallback(KeyBindingsNames.OPEN_CHAT) { _, _ -> + openChat() + } + hudRenderer.renderWindow.registerKeyCallback(KeyBindingsNames.CLOSE_CHAT) { _, _ -> + closeChat() + } + } + + override fun screenChangeResizeCallback(screenDimensions: Vec2i) { + layout.sizing.minSize.x = screenDimensions.x + layout.sizing.maxSize.x = screenDimensions.x + layout.sizing.validate() + layout.apply() + } + + fun openChat() { + hudRenderer.renderWindow.currentKeyConsumer = inputField + hudRenderer.renderWindow.currentElement.remove(KeyBindingsNames.WHEN_IN_GAME) + hudRenderer.renderWindow.currentElement.add(KeyBindingsNames.WHEN_IN_CHAT) + } + + fun closeChat() { + inputField.clearText() + hudRenderer.renderWindow.currentKeyConsumer = null + hudRenderer.renderWindow.currentElement.remove(KeyBindingsNames.WHEN_IN_CHAT) + hudRenderer.renderWindow.currentElement.add(KeyBindingsNames.WHEN_IN_GAME) + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/nodes/layout/AbsoluteLayout.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/nodes/layout/AbsoluteLayout.kt index 11631d71a..23fbf43e1 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/nodes/layout/AbsoluteLayout.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/nodes/layout/AbsoluteLayout.kt @@ -83,8 +83,7 @@ open class AbsoluteLayout( private fun recalculateSize() { if (children.isEmpty()) { - sizing.currentSize.x = sizing.minSize.x - sizing.currentSize.y = sizing.minSize.y + sizing.currentSize = Vec2i(sizing.minSize) } else { for ((childNode, start) in children) { checkSize(childNode, start) diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/nodes/primitive/LabelNode.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/nodes/primitive/LabelNode.kt index a4172bd73..9ac549416 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/nodes/primitive/LabelNode.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/nodes/primitive/LabelNode.kt @@ -37,6 +37,7 @@ class LabelNode( prepare() apply() } + var sText: String get() = text.message set(value) { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/nodes/properties/NodeSizing.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/nodes/properties/NodeSizing.kt index b90306926..7fd3e6103 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/nodes/properties/NodeSizing.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/nodes/properties/NodeSizing.kt @@ -13,14 +13,20 @@ package de.bixilon.minosoft.gui.rendering.hud.nodes.properties +import de.bixilon.minosoft.util.MMath import glm_.vec2.Vec2i data class NodeSizing( - val minSize: Vec2i = Vec2i(0, 0), - val margin: Spacing = Spacing(), - val padding: Spacing = Spacing(), - val maxSize: Vec2i = Vec2i(Int.MAX_VALUE, Int.MAX_VALUE), + var minSize: Vec2i = Vec2i(0, 0), + var margin: Spacing = Spacing(0, 0, 0, 0), + var padding: Spacing = Spacing(0, 0, 0, 0), + var maxSize: Vec2i = Vec2i(Int.MAX_VALUE, Int.MAX_VALUE), var forceAlign: NodeAlignment? = null, ) { - val currentSize: Vec2i = Vec2i(minSize) + var currentSize: Vec2i = Vec2i(minSize) + + + fun validate() { + MMath.clamp(currentSize, minSize, maxSize) + } } diff --git a/src/main/java/de/bixilon/minosoft/util/MMath.kt b/src/main/java/de/bixilon/minosoft/util/MMath.kt index 71d8c01aa..b48c01252 100644 --- a/src/main/java/de/bixilon/minosoft/util/MMath.kt +++ b/src/main/java/de/bixilon/minosoft/util/MMath.kt @@ -13,6 +13,8 @@ package de.bixilon.minosoft.util +import glm_.vec2.Vec2i + object MMath { fun minClamp(value: Int, min: Int): Int { @@ -22,6 +24,12 @@ object MMath { return value } + fun clamp(value: Vec2i, min: Vec2i, max: Vec2i): Vec2i { + value.x = clamp(value.x, min.x, max.x) + value.y = clamp(value.y, min.y, max.y) + return value + } + fun clamp(value: Int, min: Int, max: Int): Int { if (value < min) { return min