diff --git a/src/test/java/de/bixilon/minosoft/data/registries/biomes/BiomeTest.kt b/src/integration-test/kotlin/de/bixilon/minosoft/data/registries/versions/registries/pixlyzer/1_20_4.kt similarity index 65% rename from src/test/java/de/bixilon/minosoft/data/registries/biomes/BiomeTest.kt rename to src/integration-test/kotlin/de/bixilon/minosoft/data/registries/versions/registries/pixlyzer/1_20_4.kt index 58560be4b..8cdd0a8d1 100644 --- a/src/test/java/de/bixilon/minosoft/data/registries/biomes/BiomeTest.kt +++ b/src/integration-test/kotlin/de/bixilon/minosoft/data/registries/versions/registries/pixlyzer/1_20_4.kt @@ -11,17 +11,9 @@ * This software is not affiliated with Mojang AB, the original developer of Minecraft. */ -package de.bixilon.minosoft.data.registries.biomes +package de.bixilon.minosoft.data.registries.versions.registries.pixlyzer -import de.bixilon.minosoft.data.registries.identified.Namespaces.minecraft -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test +import org.testng.annotations.Test -class BiomeTest { - - @Test - fun `color map index`() { - val biome = Biome(minecraft("plains"), temperature = 0.8f, downfall = 0.4f) - assertEquals(biome.colorMapPixelIndex, 44338) - } -} +@Test(groups = ["pixlyzer"], dependsOnGroups = ["version"], priority = Int.MAX_VALUE, timeOut = 15000L) +class `1_20_4` : PixLyzerLoadingTest("1.20.4") diff --git a/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/system/base/texture/data/buffer/RGB8BufferTest.kt b/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/system/base/texture/data/buffer/RGB8BufferTest.kt index 35997f670..ce2fbdd64 100644 --- a/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/system/base/texture/data/buffer/RGB8BufferTest.kt +++ b/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/system/base/texture/data/buffer/RGB8BufferTest.kt @@ -67,6 +67,13 @@ class RGB8BufferTest { assertEquals(source.getA(3, 3), 0xFF) } + fun `get rgb at 3,3`() { + val source = RGB8Buffer(Vec2i(12, 13)) + source.data.put(117 + 0, 0x11).put(117 + 1, 0x22).put(117 + 2, 0x33) + val rgba = source.getRGB(3, 3) + assertEquals(rgba, 0x112233) + } + fun `put complete texture`() { val source = RGB8Buffer(Vec2i(12, 13)) diff --git a/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/system/base/texture/data/buffer/RGBA8BufferTest.kt b/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/system/base/texture/data/buffer/RGBA8BufferTest.kt index 856e7c8ca..2352b1da7 100644 --- a/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/system/base/texture/data/buffer/RGBA8BufferTest.kt +++ b/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/system/base/texture/data/buffer/RGBA8BufferTest.kt @@ -69,6 +69,12 @@ class RGBA8BufferTest { assertEquals(source.getB(3, 3), 0x33) assertEquals(source.getA(3, 3), 0x44) } + fun `get rgb at 3,3`() { + val source = RGBA8Buffer(Vec2i(12, 13)) + source.data.put(156 + 0, 0x11).put(156 + 1, 0x22).put(156 + 2, 0x33).put(156 + 3, 0x44) + val rgba = source.getRGB(3, 3) + assertEquals(rgba, 0x112233) + } fun `put complete texture`() { diff --git a/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/tint/tints/ColorMapTintTest.kt b/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/tint/tints/ColorMapTintTest.kt new file mode 100644 index 000000000..2360c7f63 --- /dev/null +++ b/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/tint/tints/ColorMapTintTest.kt @@ -0,0 +1,37 @@ +/* + * Minosoft + * Copyright (C) 2020-2023 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.tint.tints + +import de.bixilon.minosoft.data.registries.biomes.Biome +import de.bixilon.minosoft.data.registries.identified.Namespaces.minecraft +import org.testng.Assert.assertEquals +import org.testng.annotations.Test + +@Test(groups = ["biome"]) +class ColorMapTintTest { + + @Test + fun `plains color map index`() { + val biome = Biome(minecraft("plains"), temperature = 0.8f, downfall = 0.4f) + assertEquals(biome.temperatureIndex, 50) + assertEquals(biome.downfallIndex, 173) + } + + @Test + fun `dessert color map index`() { + val biome = Biome(minecraft("dessert"), temperature = 2.0f, downfall = 0.0f) + assertEquals(biome.temperatureIndex, 0) + assertEquals(biome.downfallIndex, 255) + } +} diff --git a/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/tint/tints/grass/GrassTintCalculatorTest.kt b/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/tint/tints/grass/GrassTintCalculatorTest.kt new file mode 100644 index 000000000..16bfb1f7b --- /dev/null +++ b/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/tint/tints/grass/GrassTintCalculatorTest.kt @@ -0,0 +1,35 @@ +/* + * Minosoft + * Copyright (C) 2020-2023 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.tint.tints.grass + +import de.bixilon.minosoft.assets.MemoryAssetsManager +import org.testng.Assert.assertEquals +import org.testng.annotations.Test + +@Test(groups = ["tint"]) +class GrassTintCalculatorTest { + private val map by lazy { + val map = GrassTintCalculator() + val assets = MemoryAssetsManager() + assets.push(GrassTintCalculator.FILE, GrassTintCalculatorTest::class.java.getResourceAsStream("/tint/grass.png")!!.readAllBytes()) + map.init(assets) + + return@lazy map + } + + + fun `color of dessert`() { + assertEquals(map.getColor(255, 0), 0xBFB755) + } +} diff --git a/src/integration-test/resources/tint/foliage.png b/src/integration-test/resources/tint/foliage.png new file mode 100644 index 000000000..d58fce229 Binary files /dev/null and b/src/integration-test/resources/tint/foliage.png differ diff --git a/src/integration-test/resources/tint/grass.png b/src/integration-test/resources/tint/grass.png new file mode 100644 index 000000000..5b946547e Binary files /dev/null and b/src/integration-test/resources/tint/grass.png differ diff --git a/src/main/java/de/bixilon/minosoft/assets/minecraft/JarAssetsManager.kt b/src/main/java/de/bixilon/minosoft/assets/minecraft/JarAssetsManager.kt index 5da45e193..b3f8dff5e 100644 --- a/src/main/java/de/bixilon/minosoft/assets/minecraft/JarAssetsManager.kt +++ b/src/main/java/de/bixilon/minosoft/assets/minecraft/JarAssetsManager.kt @@ -25,7 +25,7 @@ import de.bixilon.minosoft.assets.properties.manager.pack.PackProperties import de.bixilon.minosoft.assets.util.FileAssetsTypes import de.bixilon.minosoft.assets.util.FileAssetsUtil import de.bixilon.minosoft.assets.util.HashTypes -import de.bixilon.minosoft.assets.util.InputStreamUtil.readArchive +import de.bixilon.minosoft.assets.util.InputStreamUtil.readTarArchive import de.bixilon.minosoft.assets.util.InputStreamUtil.readZipArchive import de.bixilon.minosoft.assets.util.PathUtil import de.bixilon.minosoft.config.profile.profiles.resources.ResourcesProfile @@ -66,7 +66,7 @@ class JarAssetsManager( private fun tryLoadAssets(): Boolean { - val assets = FileAssetsUtil.readOrNull(jarAssetsHash, FileAssetsTypes.GAME, verify = profile.verify)?.let { ByteArrayInputStream(it).readArchive() } ?: return false + val assets = FileAssetsUtil.readOrNull(jarAssetsHash, FileAssetsTypes.GAME, verify = profile.verify)?.let { ByteArrayInputStream(it).readTarArchive() } ?: return false for ((path, data) in assets) { this.assets[path.removePrefix("assets/" + Namespaces.MINECRAFT + "/")] = data diff --git a/src/main/java/de/bixilon/minosoft/assets/util/InputStreamUtil.kt b/src/main/java/de/bixilon/minosoft/assets/util/InputStreamUtil.kt index 5b4357ad8..c16d69623 100644 --- a/src/main/java/de/bixilon/minosoft/assets/util/InputStreamUtil.kt +++ b/src/main/java/de/bixilon/minosoft/assets/util/InputStreamUtil.kt @@ -21,9 +21,7 @@ import de.bixilon.kutil.cast.CastUtil.unsafeCast import de.bixilon.kutil.json.JsonObject import de.bixilon.mbf.MBFBinaryReader import de.bixilon.minosoft.util.json.Jackson -import de.matthiasmann.twl.utils.PNGDecoder import org.kamranzafar.jtar.TarInputStream -import org.lwjgl.BufferUtils import java.io.InputStream import java.util.zip.ZipInputStream @@ -50,13 +48,7 @@ object InputStreamUtil { } fun InputStream.readJsonObject(close: Boolean = true): JsonObject { - try { - return Jackson.MAPPER.readValue(this, Jackson.JSON_MAP_TYPE) - } finally { - if (close) { - this.close() - } - } + return readJson(close = close, reader = Jackson.MAP_READER) } inline fun InputStream.readJson(close: Boolean = true): T { @@ -89,7 +81,7 @@ object InputStreamUtil { } } - fun InputStream.readArchive(): Map { + fun InputStream.readTarArchive(): Map { val content: MutableMap = mutableMapOf() val stream = TarInputStream(this) while (true) { @@ -111,21 +103,6 @@ object InputStreamUtil { return content } - fun InputStream.readRGBArray(): IntArray { - val decoder = PNGDecoder(this) - - val buffer = BufferUtils.createByteBuffer(decoder.width * decoder.height * PNGDecoder.Format.RGB.numComponents) - decoder.decode(buffer, decoder.width * PNGDecoder.Format.RGB.numComponents, PNGDecoder.Format.RGB) - buffer.flip() - val colors = IntArray(decoder.width * decoder.height) - - for (i in colors.indices) { - colors[i] = ((buffer.get().toInt() and 0xFF) shl 16) or ((buffer.get().toInt() and 0xFF) shl 8) or (buffer.get().toInt() and 0xFF) - } - - return colors - } - fun InputStream.readMBFMap(): Map { return MBFBinaryReader(this).readMBF().data.unsafeCast() } diff --git a/src/main/java/de/bixilon/minosoft/data/registries/biomes/Biome.kt b/src/main/java/de/bixilon/minosoft/data/registries/biomes/Biome.kt index c700a3898..3b46cf765 100644 --- a/src/main/java/de/bixilon/minosoft/data/registries/biomes/Biome.kt +++ b/src/main/java/de/bixilon/minosoft/data/registries/biomes/Biome.kt @@ -12,7 +12,6 @@ */ package de.bixilon.minosoft.data.registries.biomes -import de.bixilon.kotlinglm.func.common.clamp import de.bixilon.kutil.json.JsonUtil.toJsonObject import de.bixilon.kutil.primitive.FloatUtil.toFloat import de.bixilon.minosoft.data.registries.identified.ResourceLocation @@ -20,9 +19,8 @@ import de.bixilon.minosoft.data.registries.registries.Registries import de.bixilon.minosoft.data.registries.registries.registry.RegistryItem import de.bixilon.minosoft.data.registries.registries.registry.codec.IdentifierCodec import de.bixilon.minosoft.data.text.formatting.color.RGBColor -import de.bixilon.minosoft.gui.rendering.RenderConstants import de.bixilon.minosoft.gui.rendering.tint.TintManager.Companion.jsonTint -import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition +import de.bixilon.minosoft.gui.rendering.tint.tints.ColorMapTint data class Biome( override val identifier: ResourceLocation, @@ -34,26 +32,15 @@ data class Biome( val waterFogColor: RGBColor? = null, val precipitation: BiomePrecipitation? = null, ) : RegistryItem() { - val grassColorModifier = GrassColorModifiers.BIOME_MAP[identifier] - val temperatureColorMapCoordinate = getColorMapCoordinate(temperature) - val downfallColorMapCoordinate = getColorMapCoordinate(downfall * temperature) - val colorMapPixelIndex = downfallColorMapCoordinate shl 8 or temperatureColorMapCoordinate + val grassModifier = GrassColorModifiers.BIOME_MAP[identifier] - fun getClampedTemperature(height: Int): Int { - return getColorMapCoordinate((temperature + ((height - ProtocolDefinition.SEA_LEVEL_HEIGHT).clamp(1, Int.MAX_VALUE) * ProtocolDefinition.HEIGHT_SEA_LEVEL_MODIFIER)).clamp(0.0f, 1.0f)) - } + val temperatureIndex = ColorMapTint.getIndex(temperature) + val downfallIndex = ColorMapTint.getIndex(downfall * temperature) - override fun toString(): String { - return identifier.toString() - } companion object : IdentifierCodec { - private fun getColorMapCoordinate(value: Float): Int { - return ((1.0 - value.clamp(0.0f, 1.0f)) * RenderConstants.COLORMAP_SIZE).toInt() - } - override fun deserialize(registries: Registries?, identifier: ResourceLocation, data: Map): Biome { val effects = data["effects"].toJsonObject() // nbt data val skyColor = (data["sky_color"] ?: effects?.get("sky_color"))?.jsonTint() 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 9fa27f365..252f3054b 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/RenderConstants.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/RenderConstants.kt @@ -18,9 +18,6 @@ import de.bixilon.minosoft.data.text.formatting.color.RGBColor import de.bixilon.minosoft.gui.rendering.textures.TextureUtil.texture object RenderConstants { - const val COLORMAP_SIZE = 255 - - val TEXT_BACKGROUND_COLOR = RGBColor(0, 0, 0, 80) diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/queue/meshing/ChunkMeshingQueue.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/queue/meshing/ChunkMeshingQueue.kt index d29cc6c27..3c4a70bae 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/queue/meshing/ChunkMeshingQueue.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/queue/meshing/ChunkMeshingQueue.kt @@ -34,7 +34,7 @@ class ChunkMeshingQueue( @Volatile private var working = false - private val queue: MutableList = mutableListOf() + private val queue: MutableList = ArrayList() private val set: MutableSet = HashSet() private val lock = SimpleLock() diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/array/StaticTextureArray.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/array/StaticTextureArray.kt index c4dba69e4..c51354837 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/array/StaticTextureArray.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/array/StaticTextureArray.kt @@ -21,7 +21,7 @@ import de.bixilon.kutil.concurrent.pool.runnable.ForcePooledRunnable import de.bixilon.kutil.concurrent.pool.runnable.SimplePoolRunnable import de.bixilon.kutil.latch.AbstractLatch import de.bixilon.kutil.latch.AbstractLatch.Companion.child -import de.bixilon.minosoft.assets.util.InputStreamUtil.readAsString +import de.bixilon.minosoft.assets.util.InputStreamUtil.readJson import de.bixilon.minosoft.data.registries.identified.ResourceLocation import de.bixilon.minosoft.gui.rendering.RenderContext import de.bixilon.minosoft.gui.rendering.system.base.texture.TextureStates @@ -31,7 +31,6 @@ import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.Texture import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.file.PNGTexture import de.bixilon.minosoft.gui.rendering.textures.properties.ImageProperties import de.bixilon.minosoft.util.KUtil.toResourceLocation -import de.bixilon.minosoft.util.json.Jackson import java.util.concurrent.atomic.AtomicInteger abstract class StaticTextureArray( @@ -88,8 +87,8 @@ abstract class StaticTextureArray( private fun readImageProperties(texture: ResourceLocation): ImageProperties? { try { - val data = context.connection.assetsManager.getOrNull("$texture.mcmeta".toResourceLocation())?.readAsString() ?: return null - return Jackson.MAPPER.readValue(data, ImageProperties::class.java) + val stream = context.connection.assetsManager.getOrNull("$texture.mcmeta".toResourceLocation()) ?: return null + return stream.readJson(reader = ImageProperties.READER) } catch (error: Throwable) { error.printStackTrace() } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/data/buffer/RGB8Buffer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/data/buffer/RGB8Buffer.kt index 88e4e041f..dcc34d1e4 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/data/buffer/RGB8Buffer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/data/buffer/RGB8Buffer.kt @@ -62,6 +62,11 @@ class RGB8Buffer( return (this[stride + 0] shl 24) or (this[stride + 1] shl 16) or (this[stride + 2] shl 8) or 0xFF } + override fun getRGB(x: Int, y: Int): Int { + val stride = stride(x, y) + return (this[stride + 0] shl 16) or (this[stride + 1] shl 8) or this[stride + 2] + } + override fun getR(x: Int, y: Int) = this[stride(x, y) + 0] override fun getG(x: Int, y: Int) = this[stride(x, y) + 1] @@ -70,6 +75,7 @@ class RGB8Buffer( private fun stride(x: Int, y: Int): Int { + if (x >= size.x || y >= size.y) throw IllegalArgumentException("Can not access pixel at ($x,$y), exceeds size: $size") return ((size.x * y) + x) * bytes } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/data/buffer/RGBA8Buffer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/data/buffer/RGBA8Buffer.kt index 98f861503..19962ce6f 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/data/buffer/RGBA8Buffer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/data/buffer/RGBA8Buffer.kt @@ -58,18 +58,21 @@ class RGBA8Buffer( override fun getRGBA(x: Int, y: Int): Int { val stride = stride(x, y) - if (stride > data.capacity()) { - throw IllegalArgumentException("Can not access pixel at ($x,$y), exceeds size: $size") - } return (this[stride + 0] shl 24) or (this[stride + 1] shl 16) or (this[stride + 2] shl 8) or (this[stride + 3] shl 0) } + override fun getRGB(x: Int, y: Int): Int { + val stride = stride(x, y) + return (this[stride + 0] shl 16) or (this[stride + 1] shl 8) or this[stride + 2] + } + override fun getR(x: Int, y: Int) = this[stride(x, y) + 0] override fun getG(x: Int, y: Int) = this[stride(x, y) + 1] override fun getB(x: Int, y: Int) = this[stride(x, y) + 2] override fun getA(x: Int, y: Int) = this[stride(x, y) + 3] private fun stride(x: Int, y: Int): Int { + if (x >= size.x || y >= size.y) throw IllegalArgumentException("Can not access pixel at ($x,$y), exceeds size: $size") return ((size.x * y) + x) * bytes } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/data/buffer/TextureBuffer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/data/buffer/TextureBuffer.kt index 5dc525c47..305020bbd 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/data/buffer/TextureBuffer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/data/buffer/TextureBuffer.kt @@ -55,6 +55,8 @@ interface TextureBuffer { fun getB(x: Int, y: Int): Int fun getA(x: Int, y: Int): Int + fun getRGB(x: Int, y: Int): Int + fun getRGBA(x: Int, y: Int): Int fun setRGBA(x: Int, y: Int, value: Int) fun setRGBA(x: Int, y: Int, red: Int, green: Int, blue: Int, alpha: Int) diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/textures/properties/ImageProperties.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/textures/properties/ImageProperties.kt index 0849b796b..f9ecbb2cb 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/textures/properties/ImageProperties.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/textures/properties/ImageProperties.kt @@ -1,6 +1,6 @@ /* * Minosoft - * Copyright (C) 2021 Moritz Zwerger + * Copyright (C) 2020-2023 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. * @@ -14,6 +14,7 @@ package de.bixilon.minosoft.gui.rendering.textures.properties import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.Texture +import de.bixilon.minosoft.util.json.Jackson data class ImageProperties( val texture: TextureProperties = TextureProperties(), @@ -27,5 +28,6 @@ data class ImageProperties( companion object { val DEFAULT = ImageProperties() + val READER = Jackson.MAPPER.readerFor(ImageProperties::class.java) } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/tint/tints/ColorMapTint.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/tint/tints/ColorMapTint.kt new file mode 100644 index 000000000..b428506ea --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/tint/tints/ColorMapTint.kt @@ -0,0 +1,62 @@ +/* + * Minosoft + * Copyright (C) 2020-2023 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.tint.tints + +import de.bixilon.kutil.exception.ExceptionUtil.ignoreAll +import de.bixilon.minosoft.assets.AssetsManager +import de.bixilon.minosoft.data.registries.identified.ResourceLocation +import de.bixilon.minosoft.gui.rendering.system.base.texture.data.buffer.TextureBuffer +import de.bixilon.minosoft.gui.rendering.textures.TextureUtil.readTexture +import de.bixilon.minosoft.gui.rendering.tint.TintProvider +import de.bixilon.minosoft.util.logging.Log +import de.bixilon.minosoft.util.logging.LogLevels +import de.bixilon.minosoft.util.logging.LogMessageType + +abstract class ColorMapTint( + private val file: ResourceLocation, +) : TintProvider { + protected var map: IntArray? = null + + fun init(assets: AssetsManager) { + val map = ignoreAll { assets[file].readTexture() } ?: return + if (map.size.x != SIZE || map.size.y != SIZE) { + Log.log(LogMessageType.LOADING, LogLevels.WARN) { "Color map ($file) has invalid size: ${map.size}" } + return + } + this.map = map.toColorMap() + } + + private fun TextureBuffer.toColorMap(): IntArray { + val array = IntArray(size.x * size.y) + var index = 0 + for (y in 0 until size.y) { + for (x in 0 until size.x) { + array[index++] = getRGB(x, y) + } + } + return array + } + + companion object { + const val SIZE = 256 + + fun getIndex(value: Float): Int { + if (value <= 0.0f) return SIZE - 1 + if (value >= 1.0f) return 0 + + val delta = 1.0f - value + return (delta * (SIZE - 1)).toInt() + } + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/tint/tints/grass/GrassTintCalculator.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/tint/tints/grass/GrassTintCalculator.kt index 2bdf32e62..1a15d6b8f 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/tint/tints/grass/GrassTintCalculator.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/tint/tints/grass/GrassTintCalculator.kt @@ -13,48 +13,33 @@ package de.bixilon.minosoft.gui.rendering.tint.tints.grass -import de.bixilon.kutil.exception.ExceptionUtil.ignoreAll -import de.bixilon.minosoft.assets.AssetsManager -import de.bixilon.minosoft.assets.util.InputStreamUtil.readRGBArray +import de.bixilon.minosoft.data.container.stack.ItemStack import de.bixilon.minosoft.data.registries.biomes.Biome import de.bixilon.minosoft.data.registries.biomes.GrassColorModifiers import de.bixilon.minosoft.data.registries.blocks.state.BlockState import de.bixilon.minosoft.data.registries.blocks.types.building.dirt.GrassBlock +import de.bixilon.minosoft.data.registries.identified.Namespaces.minecraft import de.bixilon.minosoft.data.text.formatting.color.Colors import de.bixilon.minosoft.gui.rendering.textures.TextureUtil.texture -import de.bixilon.minosoft.gui.rendering.tint.TintProvider -import de.bixilon.minosoft.util.KUtil.toResourceLocation +import de.bixilon.minosoft.gui.rendering.tint.tints.ColorMapTint -class GrassTintCalculator : TintProvider { - private lateinit var colorMap: IntArray +class GrassTintCalculator : ColorMapTint(FILE) { - fun init(assetsManager: AssetsManager) { - colorMap = ignoreAll { assetsManager["minecraft:colormap/grass".toResourceLocation().texture()].readRGBArray() } ?: IntArray(256) - } + fun getColor(downfallIndex: Int, temperatureIndex: Int): Int { + val map = map ?: return FALLBACK - inline fun getColor(downfall: Int, temperature: Int): Int { - return getColor(downfall shl 8 or temperature) - } - - fun getColor(colorMapPixelIndex: Int): Int { - if (colorMapPixelIndex > colorMap.size) { - return 0xFF00FF // ToDo: Is this correct? Was used in my old implementation - } - val color = colorMap[colorMapPixelIndex] - if (color == 0xFFFFFF) { - return 0x48B518 - } + val color = map[downfallIndex shl 8 or temperatureIndex] + if (color == 0xFFFFFF) return 0x48B518 return color } fun getBlockColor(biome: Biome?): Int { - if (biome == null) { - return getColor(127, 255) - } - val color = getColor(biome.colorMapPixelIndex) + if (biome == null) return getColor(127, 255) - return when (biome.grassColorModifier) { + val color = getColor(biome.downfallIndex, biome.temperatureIndex) + + return when (biome.grassModifier) { null -> color GrassColorModifiers.SWAMP -> 0x6A7039 // ToDo: Biome noise is applied here GrassColorModifiers.DARK_FOREST -> (color and 0xFEFEFE) + 0x28340A shr 1 @@ -71,4 +56,13 @@ class GrassTintCalculator : TintProvider { } return getBlockColor(biome) } + + override fun getItemColor(stack: ItemStack, tintIndex: Int): Int { + return getColor(127, 255) // TODO: verify + } + + companion object { + val FILE = minecraft("colormap/grass").texture() + private const val FALLBACK = 0xFF00FF // ToDo: Is this correct? Was used in my old implementation + } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/tint/tints/plants/FoliageTintCalculator.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/tint/tints/plants/FoliageTintCalculator.kt index 8bd75ebf0..011a03008 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/tint/tints/plants/FoliageTintCalculator.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/tint/tints/plants/FoliageTintCalculator.kt @@ -13,29 +13,23 @@ package de.bixilon.minosoft.gui.rendering.tint.tints.plants -import de.bixilon.kutil.exception.ExceptionUtil.ignoreAll -import de.bixilon.minosoft.assets.AssetsManager -import de.bixilon.minosoft.assets.util.InputStreamUtil.readRGBArray +import de.bixilon.kotlinglm.func.common.clamp import de.bixilon.minosoft.data.container.stack.ItemStack import de.bixilon.minosoft.data.registries.biomes.Biome import de.bixilon.minosoft.data.registries.blocks.state.BlockState +import de.bixilon.minosoft.data.registries.identified.Namespaces.minecraft import de.bixilon.minosoft.gui.rendering.textures.TextureUtil.texture -import de.bixilon.minosoft.gui.rendering.tint.TintProvider -import de.bixilon.minosoft.util.KUtil.toResourceLocation +import de.bixilon.minosoft.gui.rendering.tint.tints.ColorMapTint -class FoliageTintCalculator : TintProvider { - private lateinit var colorMap: IntArray - - fun init(assetsManager: AssetsManager) { - colorMap = ignoreAll { assetsManager["minecraft:colormap/foliage".toResourceLocation().texture()].readRGBArray() } ?: IntArray(256) - } +class FoliageTintCalculator : ColorMapTint(FILE) { fun getBlockColor(biome: Biome?, y: Int): Int { - if (biome == null) { - return FALLBACK_COLOR - } + if (biome == null) return FALLBACK_COLOR + val map = this.map ?: return FALLBACK_COLOR + // ToDo: Override - return colorMap[biome.downfallColorMapCoordinate shl 8 or biome.getClampedTemperature(y)] + val temperature = modifyTemperature(biome.temperature, y) + return map[biome.downfallIndex shl 8 or temperature] } override fun getBlockColor(blockState: BlockState, biome: Biome?, x: Int, y: Int, z: Int, tintIndex: Int): Int { @@ -51,6 +45,19 @@ class FoliageTintCalculator : TintProvider { } companion object { + private val FILE = minecraft("colormap/foliage").texture() private const val FALLBACK_COLOR = 0x48B518 + + // not sure if that is accurate or relevant + private const val SEA_LEVEL = 62 + private const val SEA_LEVEL_MODIFIER = 0.00166667f + + + fun modifyTemperature(temperature: Float, height: Int): Int { + val modifier = maxOf(1, height - SEA_LEVEL) * SEA_LEVEL_MODIFIER + val modified = (temperature + modifier).clamp(0.0f, 1.0f) + + return getIndex(modified) + } } } diff --git a/src/main/java/de/bixilon/minosoft/protocol/protocol/ProtocolDefinition.java b/src/main/java/de/bixilon/minosoft/protocol/protocol/ProtocolDefinition.java index c70587109..64836a20f 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/protocol/ProtocolDefinition.java +++ b/src/main/java/de/bixilon/minosoft/protocol/protocol/ProtocolDefinition.java @@ -68,9 +68,6 @@ public final class ProtocolDefinition { public static final float VELOCITY_NETWORK_DIVIDER = 8000.0f; - public static final int SEA_LEVEL_HEIGHT = 62; - - public static final float HEIGHT_SEA_LEVEL_MODIFIER = 0.00166667f; public static final RGBColor DEFAULT_COLOR = ChatColors.WHITE; diff --git a/src/main/java/de/bixilon/minosoft/util/json/Jackson.kt b/src/main/java/de/bixilon/minosoft/util/json/Jackson.kt index 1e97343ac..e5792c6f7 100644 --- a/src/main/java/de/bixilon/minosoft/util/json/Jackson.kt +++ b/src/main/java/de/bixilon/minosoft/util/json/Jackson.kt @@ -64,6 +64,7 @@ object Jackson { val JSON_MAP_TYPE: MapType = MAPPER.typeFactory.constructMapType(HashMap::class.java, Any::class.java, Any::class.java) + val MAP_READER = MAPPER.readerFor(JSON_MAP_TYPE) fun init() = Unit }