diff --git a/src/main/java/de/bixilon/minosoft/config/config/game/GameConfig.kt b/src/main/java/de/bixilon/minosoft/config/config/game/GameConfig.kt index 36835bf75..c08806fd6 100644 --- a/src/main/java/de/bixilon/minosoft/config/config/game/GameConfig.kt +++ b/src/main/java/de/bixilon/minosoft/config/config/game/GameConfig.kt @@ -17,6 +17,7 @@ import de.bixilon.minosoft.config.config.game.controls.ControlsGameConfig import de.bixilon.minosoft.config.config.game.entities.EntitiesConfig import de.bixilon.minosoft.config.config.game.graphics.GraphicsGameConfig import de.bixilon.minosoft.config.config.game.sound.SoundConfig +import de.bixilon.minosoft.config.config.game.world.WorldConfig import de.bixilon.minosoft.data.mappings.ResourceLocation import de.bixilon.minosoft.gui.rendering.hud.elements.primitive.HUDElement @@ -29,4 +30,5 @@ data class GameConfig( var camera: CameraGameConfig = CameraGameConfig(), var sound: SoundConfig = SoundConfig(), var entities: EntitiesConfig = EntitiesConfig(), + var world: WorldConfig = WorldConfig(), ) diff --git a/src/main/java/de/bixilon/minosoft/config/config/game/world/ChunkBorderConfig.kt b/src/main/java/de/bixilon/minosoft/config/config/game/world/ChunkBorderConfig.kt new file mode 100644 index 000000000..651d3d429 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/config/config/game/world/ChunkBorderConfig.kt @@ -0,0 +1,18 @@ +/* + * 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.config.config.game.world + +data class ChunkBorderConfig( + var enabled: Boolean = false, +) diff --git a/src/main/java/de/bixilon/minosoft/config/config/game/world/WorldConfig.kt b/src/main/java/de/bixilon/minosoft/config/config/game/world/WorldConfig.kt new file mode 100644 index 000000000..05cca2519 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/config/config/game/world/WorldConfig.kt @@ -0,0 +1,20 @@ +/* + * 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.config.config.game.world + +import com.squareup.moshi.Json + +data class WorldConfig( + @Json(name = "chunk_borders") var chunkBorders: ChunkBorderConfig = ChunkBorderConfig(), +) diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/RenderConstants.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/RenderConstants.kt index b4ae19899..d473f0388 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/RenderConstants.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/RenderConstants.kt @@ -80,4 +80,6 @@ object RenderConstants { const val MAX_BLOCK_OUTLINE_RAYCAST_DISTANCE = 5.0f const val MAXIMUM_PARTICLE_AMOUNT = 200000 + + const val DEFAULT_LINE_WIDTH = 1.0f / 128.0f } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/RenderWindow.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/RenderWindow.kt index 52da4d945..2f5c0e791 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/RenderWindow.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/RenderWindow.kt @@ -17,6 +17,7 @@ import de.bixilon.minosoft.Minosoft import de.bixilon.minosoft.config.StaticConfiguration import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames import de.bixilon.minosoft.data.registries.ResourceLocation +import de.bixilon.minosoft.gui.rendering.chunk.ChunkBorderRenderer import de.bixilon.minosoft.gui.rendering.chunk.WorldRenderer import de.bixilon.minosoft.gui.rendering.chunk.block.outline.BlockOutlineRenderer import de.bixilon.minosoft.gui.rendering.entities.EntityHitBoxRenderer @@ -119,6 +120,9 @@ class RenderWindow( if (Minosoft.config.config.game.entities.hitBox.enabled) { registerRenderer(EntityHitBoxRenderer) } + if (Minosoft.config.config.game.world.chunkBorders.enabled) { + registerRenderer(ChunkBorderRenderer) + } registerRenderer(HUDRenderer) } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/ChunkBorderRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/ChunkBorderRenderer.kt new file mode 100644 index 000000000..37445217e --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/ChunkBorderRenderer.kt @@ -0,0 +1,130 @@ +/* + * 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.chunk + +import de.bixilon.minosoft.data.registries.ResourceLocation +import de.bixilon.minosoft.data.text.ChatColors +import de.bixilon.minosoft.gui.rendering.RenderConstants +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.util.mesh.LineMesh +import de.bixilon.minosoft.protocol.network.connection.PlayConnection +import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition +import glm_.vec2.Vec2i +import glm_.vec3.Vec3 +import org.lwjgl.opengl.GL11.* + +class ChunkBorderRenderer( + val connection: PlayConnection, + val renderWindow: RenderWindow, +) : Renderer { + private var lastChunkPosition: Vec2i? = null + private var lastMesh: LineMesh? = null + + + private fun prepare() { + val chunkPosition = renderWindow.connection.player.positionInfo.chunkPosition + if (chunkPosition == lastChunkPosition && lastMesh != null) { + return + } + lastMesh?.unload(false) + val mesh = LineMesh() + + val dimension = renderWindow.connection.world.dimension ?: return + val basePosition = chunkPosition * Vec2i(ProtocolDefinition.SECTION_WIDTH_X, ProtocolDefinition.SECTION_WIDTH_Z) + + + // vertical lines + for (x in 0..ProtocolDefinition.SECTION_WIDTH_X) { + val color = when { + x % ProtocolDefinition.SECTION_WIDTH_X == 0 -> ChatColors.BLUE + x % 2 == 0 -> ChatColors.GREEN + else -> ChatColors.YELLOW + } + + mesh.drawLine(Vec3(basePosition.x + x, dimension.minY, basePosition.y), Vec3(basePosition.x + x, dimension.height, basePosition.y), RenderConstants.DEFAULT_LINE_WIDTH * 5, color) + mesh.drawLine(Vec3(basePosition.x + x, dimension.minY, basePosition.y + ProtocolDefinition.SECTION_WIDTH_Z), Vec3(basePosition.x + x, dimension.height, basePosition.y + ProtocolDefinition.SECTION_WIDTH_Z), RenderConstants.DEFAULT_LINE_WIDTH * 5, color) + } + + for (z in 0..ProtocolDefinition.SECTION_WIDTH_Z) { + val color = when { + z % ProtocolDefinition.SECTION_WIDTH_Z == 0 -> ChatColors.BLUE + z % 2 == 0 -> ChatColors.GREEN + else -> ChatColors.YELLOW + } + + mesh.drawLine(Vec3(basePosition.x, dimension.minY, basePosition.y + z), Vec3(basePosition.x, dimension.height, basePosition.y + z), RenderConstants.DEFAULT_LINE_WIDTH * 5, color) + mesh.drawLine(Vec3(basePosition.x + ProtocolDefinition.SECTION_WIDTH_X, dimension.minY, basePosition.y + z), Vec3(basePosition.x + ProtocolDefinition.SECTION_WIDTH_X, dimension.height, basePosition.y + z), RenderConstants.DEFAULT_LINE_WIDTH * 5, color) + } + + // horizontal lines + for (y in dimension.minY..dimension.height) { + val borderColor = when { + y % ProtocolDefinition.SECTION_HEIGHT_Y == 0 -> ChatColors.BLUE + y % 2 == 0 -> ChatColors.GREEN + else -> ChatColors.YELLOW + } + + // x/z border + mesh.drawLine(Vec3(basePosition.x, y, basePosition.y), Vec3(basePosition.x + ProtocolDefinition.SECTION_WIDTH_X, y, basePosition.y), RenderConstants.DEFAULT_LINE_WIDTH * 5, borderColor) + mesh.drawLine(Vec3(basePosition.x, y, basePosition.y), Vec3(basePosition.x, y, basePosition.y + ProtocolDefinition.SECTION_WIDTH_Z), RenderConstants.DEFAULT_LINE_WIDTH * 5, borderColor) + mesh.drawLine(Vec3(basePosition.x + ProtocolDefinition.SECTION_WIDTH_X, y, basePosition.y + ProtocolDefinition.SECTION_WIDTH_Z), Vec3(basePosition.x + ProtocolDefinition.SECTION_WIDTH_X, y, basePosition.y), RenderConstants.DEFAULT_LINE_WIDTH * 5, borderColor) + mesh.drawLine(Vec3(basePosition.x + ProtocolDefinition.SECTION_WIDTH_X, y, basePosition.y + ProtocolDefinition.SECTION_WIDTH_Z), Vec3(basePosition.x, y, basePosition.y + ProtocolDefinition.SECTION_WIDTH_Z), RenderConstants.DEFAULT_LINE_WIDTH * 5, borderColor) + + + if (y % ProtocolDefinition.SECTION_HEIGHT_Y != 0) { + continue + } + + + for (x in 1..ProtocolDefinition.SECTION_MAX_X) { + val color = when { + x % 2 == 0 -> ChatColors.GREEN + else -> ChatColors.YELLOW + } + mesh.drawLine(Vec3(basePosition.x + x, y, basePosition.y), Vec3(basePosition.x + x, y, basePosition.y + ProtocolDefinition.SECTION_WIDTH_Z), RenderConstants.DEFAULT_LINE_WIDTH * 5, color) + } + for (z in 1..ProtocolDefinition.SECTION_MAX_Z) { + val color = when { + z % 2 == 0 -> ChatColors.GREEN + else -> ChatColors.YELLOW + } + mesh.drawLine(Vec3(basePosition.x, y, basePosition.y + z), Vec3(basePosition.x + ProtocolDefinition.SECTION_WIDTH_X, y, basePosition.y + z), RenderConstants.DEFAULT_LINE_WIDTH * 5, color) + } + } + + mesh.load() + this.lastMesh = mesh + this.lastChunkPosition = chunkPosition + } + + override fun draw() { + prepare() + val mesh = lastMesh ?: return + renderWindow.shaderManager.genericColorShader.use() + glDisable(GL_CULL_FACE) + mesh.draw() + glEnable(GL_CULL_FACE) + } + + + companion object : RendererBuilder { + override val RESOURCE_LOCATION = ResourceLocation("minosoft:chunk_borders") + + override fun build(connection: PlayConnection, renderWindow: RenderWindow): ChunkBorderRenderer { + return ChunkBorderRenderer(connection, renderWindow) + } + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/block/outline/BlockOutlineRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/block/outline/BlockOutlineRenderer.kt index 59e66af32..b1560105f 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/block/outline/BlockOutlineRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/block/outline/BlockOutlineRenderer.kt @@ -91,11 +91,11 @@ class BlockOutlineRenderer( val blockOffset = raycastHit.blockPosition.toVec3d + raycastHit.blockPosition.getWorldOffset(raycastHit.blockState.block) - currentMesh.drawVoxelShape(raycastHit.blockState.outlineShape, blockOffset, LINE_WIDTH, Minosoft.config.config.game.other.blockOutline.outlineColor) + currentMesh.drawVoxelShape(raycastHit.blockState.outlineShape, blockOffset, RenderConstants.DEFAULT_LINE_WIDTH, Minosoft.config.config.game.other.blockOutline.outlineColor) if (Minosoft.config.config.game.other.blockOutline.collisionBoxes) { - currentMesh.drawVoxelShape(raycastHit.blockState.collisionShape, blockOffset, LINE_WIDTH, Minosoft.config.config.game.other.blockOutline.collisionColor, 0.005f) + currentMesh.drawVoxelShape(raycastHit.blockState.collisionShape, blockOffset, RenderConstants.DEFAULT_LINE_WIDTH, Minosoft.config.config.game.other.blockOutline.collisionColor, 0.005f) } currentMesh.load() @@ -110,7 +110,6 @@ class BlockOutlineRenderer( companion object : RendererBuilder { override val RESOURCE_LOCATION = ResourceLocation("minosoft:block_outline") - private const val LINE_WIDTH = 1.0f / 128.0f override fun build(connection: PlayConnection, renderWindow: RenderWindow): BlockOutlineRenderer { return BlockOutlineRenderer(connection, renderWindow) diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/EntityHitBoxMesh.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/EntityHitBoxMesh.kt index 309e1516e..3f9b5e2f3 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/EntityHitBoxMesh.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/EntityHitBoxMesh.kt @@ -15,6 +15,7 @@ package de.bixilon.minosoft.gui.rendering.entities import de.bixilon.minosoft.Minosoft import de.bixilon.minosoft.data.entities.entities.Entity +import de.bixilon.minosoft.gui.rendering.RenderConstants import de.bixilon.minosoft.gui.rendering.chunk.models.AABB import de.bixilon.minosoft.gui.rendering.util.VecUtil.EMPTY import de.bixilon.minosoft.gui.rendering.util.mesh.LineMesh @@ -33,15 +34,11 @@ class EntityHitBoxMesh( entity.isInvisible -> Minosoft.config.config.game.entities.hitBox.invisibleEntitiesColor else -> Minosoft.config.config.game.entities.hitBox.hitBoxColor } - drawAABB(entity.aabb, Vec3d.EMPTY, LINE_WIDTH, hitBoxColor) + drawAABB(entity.aabb, Vec3d.EMPTY, RenderConstants.DEFAULT_LINE_WIDTH, hitBoxColor) val halfWidth = entity.dimensions.x / 2 - val eyeAABB = AABB(Vec3(-halfWidth, entity.eyeHeight - LINE_WIDTH, -halfWidth), Vec3(halfWidth, entity.eyeHeight - LINE_WIDTH, halfWidth)).hShrink(LINE_WIDTH) - drawAABB(eyeAABB, entity.position, LINE_WIDTH, Minosoft.config.config.game.entities.hitBox.eyeHeightColor) + val eyeAABB = AABB(Vec3(-halfWidth, entity.eyeHeight - RenderConstants.DEFAULT_LINE_WIDTH, -halfWidth), Vec3(halfWidth, entity.eyeHeight - RenderConstants.DEFAULT_LINE_WIDTH, halfWidth)).hShrink(RenderConstants.DEFAULT_LINE_WIDTH) + drawAABB(eyeAABB, entity.position, RenderConstants.DEFAULT_LINE_WIDTH, Minosoft.config.config.game.entities.hitBox.eyeHeightColor) } - - companion object { - private const val LINE_WIDTH = 1.0f / 128.0f - } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/input/camera/Camera.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/input/camera/Camera.kt index fe87dabbd..f557f24b3 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/input/camera/Camera.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/input/camera/Camera.kt @@ -92,6 +92,7 @@ class Camera( } yaw %= 180 val pitch = glm.clamp(yOffset + entity.rotation.pitch, -89.9, 89.9) + entity.rotation = EntityRotation(yaw, pitch) setRotation(yaw, pitch) } @@ -160,9 +161,7 @@ class Camera( return glm.lookAt(cameraPosition, cameraPosition + cameraFront, CAMERA_UP_VEC3) } - fun setRotation(yaw: Double, pitch: Double) { - entity.rotation = EntityRotation(yaw, pitch) - + private fun setRotation(yaw: Double, pitch: Double) { cameraFront = Vec3d( (yaw + 90).rad.cos * (-pitch).rad.cos, (-pitch).rad.sin,