diff --git a/src/main/java/de/bixilon/minosoft/config/StaticConfiguration.java b/src/main/java/de/bixilon/minosoft/config/StaticConfiguration.java index 8070ecab7..be9d26926 100644 --- a/src/main/java/de/bixilon/minosoft/config/StaticConfiguration.java +++ b/src/main/java/de/bixilon/minosoft/config/StaticConfiguration.java @@ -20,6 +20,7 @@ import java.io.File; public class StaticConfiguration { public static final boolean DEBUG_MODE = true; // if true, additional checks will be made to validate data, ... Decreases performance + public static final boolean BIOME_DEBUG_MODE = true; // colors all biomes according to the biome hashCode public static final boolean DEBUG_SLOW_LOADING = false; // if true, many Thread.sleep will be executed and the start will be delayed (by a lot) public static String CONFIG_FILENAME = "minosoft.json"; // Filename of minosoft's base configuration (located in AppData/Minosoft/config) public static boolean SKIP_MOJANG_AUTHENTICATION; // disables all connections to mojang diff --git a/src/main/java/de/bixilon/minosoft/data/mappings/tweaker/VersionTweaker.kt b/src/main/java/de/bixilon/minosoft/data/mappings/tweaker/VersionTweaker.kt index af501c535..799685306 100644 --- a/src/main/java/de/bixilon/minosoft/data/mappings/tweaker/VersionTweaker.kt +++ b/src/main/java/de/bixilon/minosoft/data/mappings/tweaker/VersionTweaker.kt @@ -20,7 +20,10 @@ import de.bixilon.minosoft.data.entities.entities.monster.* import de.bixilon.minosoft.data.entities.entities.vehicle.* import de.bixilon.minosoft.data.mappings.ResourceLocation import de.bixilon.minosoft.data.mappings.blocks.BlockState -import de.bixilon.minosoft.data.world.* +import de.bixilon.minosoft.data.world.BlockInfo +import de.bixilon.minosoft.data.world.Chunk +import de.bixilon.minosoft.data.world.InChunkLocation +import de.bixilon.minosoft.data.world.InChunkSectionLocation import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition import de.bixilon.minosoft.protocol.protocol.ProtocolVersions @@ -100,7 +103,7 @@ object VersionTweaker { section.setBlockInfo(location, null) continue } - section.setBlockInfo(location, BlockInfo(newBlock, blockInfo.metaData, section.blocksFloatingInfo[location] ?: BlockFloatingInfo())) + section.setBlockInfo(location, BlockInfo(newBlock, blockInfo.metaData)) } } return chunk diff --git a/src/main/java/de/bixilon/minosoft/data/text/RGBColor.java b/src/main/java/de/bixilon/minosoft/data/text/RGBColor.java index 0c2094744..b276abcde 100644 --- a/src/main/java/de/bixilon/minosoft/data/text/RGBColor.java +++ b/src/main/java/de/bixilon/minosoft/data/text/RGBColor.java @@ -38,7 +38,15 @@ public final class RGBColor implements ChatCode { if (colorString.startsWith("#")) { colorString = colorString.substring(1); } - this.color = Integer.parseInt(colorString, 16); + if (colorString.length() == 6) { + this.color = Integer.parseUnsignedInt(colorString + "ff", 16); + } else { + this.color = Integer.parseUnsignedInt(colorString, 16); + } + } + + public static RGBColor noAlpha(int color) { + return new RGBColor(color << 8 | 0xFF); } @IntRange(from = 0, to = 255) @@ -51,16 +59,31 @@ public final class RGBColor implements ChatCode { return (this.color >>> 24) & 0xFF; } + @IntRange(from = 0, to = 1) + public float getFloatRed() { + return getRed() / 255f; + } + @IntRange(from = 0, to = 255) public int getGreen() { return (this.color >>> 16) & 0xFF; } + @IntRange(from = 0, to = 1) + public float getFloatGreen() { + return getGreen() / 255f; + } + @IntRange(from = 0, to = 255) public int getBlue() { return (this.color >>> 8) & 0xFF; } + @IntRange(from = 0, to = 1) + public float getFloatBlue() { + return getBlue() / 255f; + } + @Override public int hashCode() { return this.color; @@ -86,8 +109,4 @@ public final class RGBColor implements ChatCode { public int getColor() { return this.color; } - - public static RGBColor noAlpha(int color) { - return new RGBColor(color << 8 | 0xFF); - } } diff --git a/src/main/java/de/bixilon/minosoft/data/world/BlockInfo.kt b/src/main/java/de/bixilon/minosoft/data/world/BlockInfo.kt index 7ab6b40bf..77790f04c 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/BlockInfo.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/BlockInfo.kt @@ -19,7 +19,6 @@ import de.bixilon.minosoft.data.mappings.blocks.BlockState data class BlockInfo( val block: BlockState, var metaData: BlockEntityMetaData? = null, - val info: BlockFloatingInfo = BlockFloatingInfo(), ) { constructor(block: BlockState) : this(block, null) // ToDo: For java compatibility } diff --git a/src/main/java/de/bixilon/minosoft/data/world/Chunk.kt b/src/main/java/de/bixilon/minosoft/data/world/Chunk.kt index 3a0c1d31d..32ae373ae 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/Chunk.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/Chunk.kt @@ -13,12 +13,16 @@ package de.bixilon.minosoft.data.world import de.bixilon.minosoft.data.mappings.blocks.BlockState +import de.bixilon.minosoft.data.world.biome.BiomeAccessor import java.util.* /** * Collection of chunks sections (allocated in y) */ -class Chunk(val sections: MutableMap = mutableMapOf()) { +class Chunk( + val sections: MutableMap = mutableMapOf(), + var biomeAccessor: BiomeAccessor, +) { fun getBlockInfo(location: InChunkLocation): BlockInfo? { return sections[location.getSectionHeight()]?.getBlockInfo(location.getInChunkSectionLocation()) @@ -51,7 +55,7 @@ class Chunk(val sections: MutableMap = mutableMapOf()) { it.blocks.remove(inChunkSectionLocation) return } - it.setBlockInfo(inChunkSectionLocation, BlockInfo(block, info = it.blocksFloatingInfo[inChunkSectionLocation] ?: BlockFloatingInfo())) + it.setBlockInfo(inChunkSectionLocation, BlockInfo(block)) } } diff --git a/src/main/java/de/bixilon/minosoft/data/world/ChunkSection.kt b/src/main/java/de/bixilon/minosoft/data/world/ChunkSection.kt index 8c4bdd537..1e7040ff1 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/ChunkSection.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/ChunkSection.kt @@ -19,7 +19,6 @@ import de.bixilon.minosoft.data.mappings.blocks.BlockState */ class ChunkSection constructor( val blocks: MutableMap = mutableMapOf(), - val blocksFloatingInfo: MutableMap = mutableMapOf(), ) { fun getBlockInfo(location: InChunkSectionLocation): BlockInfo? { @@ -47,6 +46,6 @@ class ChunkSection constructor( setBlockInfo(location, null) return } - setBlockInfo(location, BlockInfo(block, info = blocksFloatingInfo[location] ?: BlockFloatingInfo())) + setBlockInfo(location, BlockInfo(block)) } } diff --git a/src/main/java/de/bixilon/minosoft/data/world/World.java b/src/main/java/de/bixilon/minosoft/data/world/World.java index 55988c763..b00ac918d 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/World.java +++ b/src/main/java/de/bixilon/minosoft/data/world/World.java @@ -22,19 +22,20 @@ import de.bixilon.minosoft.data.mappings.blocks.BlockState; import javax.annotation.Nullable; import java.util.HashMap; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; /** * Collection of chunks */ public class World { - private final HashMap chunks = new HashMap<>(); + private final ConcurrentHashMap chunks = new ConcurrentHashMap<>(); private final HashBiMap entityIdMap = HashBiMap.create(); private final HashBiMap entityUUIDMap = HashBiMap.create(); private boolean hardcore; private boolean raining; private Dimension dimension; // used for sky color, etc - public HashMap getAllChunks() { + public ConcurrentHashMap getAllChunks() { return this.chunks; } diff --git a/src/main/java/de/bixilon/minosoft/data/world/BlockFloatingInfo.kt b/src/main/java/de/bixilon/minosoft/data/world/biome/BiomeAccessor.kt similarity index 82% rename from src/main/java/de/bixilon/minosoft/data/world/BlockFloatingInfo.kt rename to src/main/java/de/bixilon/minosoft/data/world/biome/BiomeAccessor.kt index 1a4dd4e15..16e5479eb 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/BlockFloatingInfo.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/biome/BiomeAccessor.kt @@ -11,12 +11,12 @@ * This software is not affiliated with Mojang AB, the original developer of Minecraft. */ -package de.bixilon.minosoft.data.world +package de.bixilon.minosoft.data.world.biome import de.bixilon.minosoft.data.mappings.biomes.Biome +import de.bixilon.minosoft.data.world.BlockPosition -data class BlockFloatingInfo( - var light: Int = 15, - var skyLight: Int = 15, - var biome: Biome? = null, // ToDo -) +interface BiomeAccessor { + + fun getBiome(position: BlockPosition): Biome +} diff --git a/src/main/java/de/bixilon/minosoft/data/world/biome/DummyBiomeAccessor.kt b/src/main/java/de/bixilon/minosoft/data/world/biome/DummyBiomeAccessor.kt new file mode 100644 index 000000000..ebc331eae --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/data/world/biome/DummyBiomeAccessor.kt @@ -0,0 +1,23 @@ +/* + * 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.data.world.biome + +import de.bixilon.minosoft.data.mappings.biomes.Biome +import de.bixilon.minosoft.data.world.BlockPosition + +class DummyBiomeAccessor(private val biome: Biome) : BiomeAccessor { + override fun getBiome(position: BlockPosition): Biome { + return biome + } +} diff --git a/src/main/java/de/bixilon/minosoft/data/world/biome/NoiseBiomeAccessor.kt b/src/main/java/de/bixilon/minosoft/data/world/biome/NoiseBiomeAccessor.kt new file mode 100644 index 000000000..65a29725c --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/data/world/biome/NoiseBiomeAccessor.kt @@ -0,0 +1,29 @@ +/* + * 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.data.world.biome + +import de.bixilon.minosoft.data.mappings.biomes.Biome +import de.bixilon.minosoft.data.world.BlockPosition + +class NoiseBiomeAccessor( + private val biomes: Array, +) : BiomeAccessor { + + override fun getBiome(position: BlockPosition): Biome { + val inChunk = position.getInChunkSectionLocation() + return biomes[(inChunk.y * 16 + ((inChunk.z / 4) * 4 + (inChunk.x / 4)))] + + // ToDo: This value is pseudo randomly generated. It depends on the seed of the world (received in join game). + } +} diff --git a/src/main/java/de/bixilon/minosoft/data/world/biome/XZBiomeAccessor.kt b/src/main/java/de/bixilon/minosoft/data/world/biome/XZBiomeAccessor.kt new file mode 100644 index 000000000..e1819f9e9 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/data/world/biome/XZBiomeAccessor.kt @@ -0,0 +1,26 @@ +/* + * 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.data.world.biome + +import de.bixilon.minosoft.data.mappings.biomes.Biome +import de.bixilon.minosoft.data.world.BlockPosition + +class XZBiomeAccessor( + private val biomes: Array, +) : BiomeAccessor { + + override fun getBiome(position: BlockPosition): Biome { + return biomes[(position.x and 0x0F) or ((position.z and 0x0F) shl 4)] + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/Camera.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/Camera.kt index cdffd0f28..6a994c5cb 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/Camera.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/Camera.kt @@ -29,7 +29,11 @@ import glm_.vec3.Vec3 import kotlin.math.cos import kotlin.math.sin -class Camera(private val connection: Connection, private var fov: Float) { +class Camera( + private val connection: Connection, + private var fov: Float, + private val renderWindow: RenderWindow, +) { private var mouseSensitivity = Minosoft.getConfig().config.game.camera.moseSensitivity private var movementSpeed = 7 var cameraPosition = Vec3(0.0f, 0.0f, 0.0f) @@ -169,6 +173,9 @@ class Camera(private val connection: Connection, private var fov: Float) { for (shader in shaders) { shader.use().setMat4("viewProjectionMatrix", calculateProjectionMatrix(screenWidth, screenHeight) * calculateViewMatrix()) } + // recalculate sky color for current biome + val blockPosition = Location(cameraPosition).toBlockPosition() + renderWindow.setSkyColor(connection.player.world.getChunk(blockPosition.getChunkLocation())?.biomeAccessor?.getBiome(blockPosition)?.skyColor ?: RenderConstants.DEFAULT_SKY_COLOR) } private fun calculateProjectionMatrix(screenWidth: Int, screenHeight: Int): Mat4 { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/RenderConstants.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/RenderConstants.kt new file mode 100644 index 000000000..35f6a700d --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/RenderConstants.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.gui.rendering + +import de.bixilon.minosoft.data.text.RGBColor + +object RenderConstants { + val DEFAULT_SKY_COLOR = RGBColor("#ecff89") +} 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 3d3a3bae6..867567d30 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/RenderWindow.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/RenderWindow.kt @@ -20,6 +20,7 @@ import de.bixilon.minosoft.config.key.KeyAction import de.bixilon.minosoft.config.key.KeyBinding import de.bixilon.minosoft.config.key.KeyCodes import de.bixilon.minosoft.data.mappings.ResourceLocation +import de.bixilon.minosoft.data.text.RGBColor import de.bixilon.minosoft.gui.rendering.chunk.ChunkRenderer import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer import de.bixilon.minosoft.gui.rendering.hud.elements.RenderStats @@ -110,7 +111,7 @@ class RenderWindow(private val connection: Connection, val rendering: Rendering) glfwTerminate() throw RuntimeException("Failed to create the GLFW window") } - camera = Camera(connection, Minosoft.getConfig().config.game.camera.fov) + camera = Camera(connection, Minosoft.getConfig().config.game.camera.fov, this) camera.init(this) @@ -210,7 +211,9 @@ class RenderWindow(private val connection: Connection, val rendering: Rendering) // Make the window visible GL.createCapabilities() - glClearColor(137 / 256f, 207 / 256f, 240 / 256f, 1.0f) + + setSkyColor(RGBColor("#fffe7a")) + glEnable(GL_DEPTH_TEST) glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) @@ -370,4 +373,8 @@ class RenderWindow(private val connection: Connection, val rendering: Rendering) } resourceLocationCallbacks.add(callback) } + + fun setSkyColor(color: RGBColor) { + glClearColor(color.floatRed, color.floatGreen, color.floatBlue, 1.0f) + } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/ChunkRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/ChunkRenderer.kt index 45926311d..22efa00f5 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/ChunkRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/ChunkRenderer.kt @@ -24,6 +24,7 @@ import de.bixilon.minosoft.gui.rendering.textures.Texture import de.bixilon.minosoft.gui.rendering.textures.TextureArray import de.bixilon.minosoft.protocol.network.Connection import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition +import de.bixilon.minosoft.util.logging.Log import glm_.vec3.Vec3 import org.lwjgl.opengl.GL11.GL_CULL_FACE import org.lwjgl.opengl.GL11.glEnable @@ -37,11 +38,9 @@ class ChunkRenderer(private val connection: Connection, private val world: World private var currentTick = 0 // for animation usage private var lastTickIncrementTime = 0L - private fun prepareChunk(chunkLocation: ChunkLocation, sectionHeight: Int, section: ChunkSection): FloatArray { + private fun prepareChunk(chunkLocation: ChunkLocation, sectionHeight: Int, section: ChunkSection, chunk: Chunk): FloatArray { val data: MutableList = mutableListOf() - // ToDo: Greedy meshing! - val below = world.allChunks[chunkLocation]?.sections?.get(sectionHeight - 1) val above = world.allChunks[chunkLocation]?.sections?.get(sectionHeight + 1) //val north = (world.allChunks[chunkLocation.getLocationByDirection(Directions.NORTH)]?: throw ChunkNotLoadedException("North not loaded")).sections?.get(sectionHeight) @@ -86,7 +85,12 @@ class ChunkRenderer(private val connection: Connection, private val world: World } val worldPosition = Vec3(position.x + chunkLocation.x * ProtocolDefinition.SECTION_WIDTH_X, position.y + sectionHeight * ProtocolDefinition.SECTION_HEIGHT_Y, position.z + chunkLocation.z * ProtocolDefinition.SECTION_WIDTH_Z) - blockInfo.block.getBlockRenderer(BlockPosition(chunkLocation, sectionHeight, position)).render(blockInfo, worldPosition, data, arrayOf(blockBelow, blockAbove, blockNorth, blockSouth, blockWest, blockEast)) + val blockPosition = BlockPosition(chunkLocation, sectionHeight, position) + if (blockPosition == BlockPosition(-103, 3, 288)) { + Log.debug("") + } + val biome = chunk.biomeAccessor.getBiome(blockPosition) + blockInfo.block.getBlockRenderer(blockPosition).render(blockInfo, biome, worldPosition, data, arrayOf(blockBelow, blockAbove, blockNorth, blockSouth, blockWest, blockEast)) } return data.toFloatArray() } @@ -142,13 +146,13 @@ class ChunkRenderer(private val connection: Connection, private val world: World fun prepareChunk(chunkLocation: ChunkLocation, chunk: Chunk) { chunkSectionsToDraw[chunkLocation] = ConcurrentHashMap() for ((sectionHeight, section) in chunk.sections) { - prepareChunkSection(chunkLocation, sectionHeight, section) + prepareChunkSection(chunkLocation, sectionHeight, section, chunk) } } - fun prepareChunkSection(chunkLocation: ChunkLocation, sectionHeight: Int, section: ChunkSection) { + fun prepareChunkSection(chunkLocation: ChunkLocation, sectionHeight: Int, section: ChunkSection, chunk: Chunk) { renderWindow.rendering.executor.execute { - val data = prepareChunk(chunkLocation, sectionHeight, section) + val data = prepareChunk(chunkLocation, sectionHeight, section, chunk) var sectionMap = chunkSectionsToDraw[chunkLocation] if (sectionMap == null) { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/renderable/BlockRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/renderable/BlockRenderer.kt index 36ee7678c..e0a7b840f 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/renderable/BlockRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/renderable/BlockRenderer.kt @@ -14,7 +14,9 @@ package de.bixilon.minosoft.gui.rendering.chunk.models.renderable import com.google.gson.JsonObject +import de.bixilon.minosoft.config.StaticConfiguration import de.bixilon.minosoft.data.Directions +import de.bixilon.minosoft.data.mappings.biomes.Biome import de.bixilon.minosoft.data.text.RGBColor import de.bixilon.minosoft.data.world.BlockInfo import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModel @@ -69,7 +71,7 @@ class BlockRenderer(data: JsonObject, parent: BlockModel) { } } - fun render(blockInfo: BlockInfo, position: Vec3, data: MutableList, neighbourBlocks: Array) { + fun render(blockInfo: BlockInfo, biome: Biome, position: Vec3, data: MutableList, neighbourBlocks: Array) { val modelMatrix = Mat4().translate(position) for (direction in Directions.DIRECTIONS) { @@ -90,8 +92,11 @@ class BlockRenderer(data: JsonObject, parent: BlockModel) { continue } - val tintColor: RGBColor? = blockInfo.block.tintColor + var tintColor: RGBColor? = blockInfo.block.tintColor + if (StaticConfiguration.BIOME_DEBUG_MODE) { + tintColor = RGBColor(biome.hashCode()) + } element.render(tintColor, textureMapping, modelMatrix, direction, data) } } diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketBlockChange.java b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketBlockChange.java index 51bb22afa..1ede39c72 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketBlockChange.java +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketBlockChange.java @@ -63,7 +63,7 @@ public class PacketBlockChange extends ClientboundPacket { section.setRawBlock(getPosition().getInChunkLocation().getInChunkSectionLocation(), getBlock()); } - connection.getRenderer().getRenderWindow().getChunkRenderer().prepareChunkSection(getPosition().getChunkLocation(), sectionHeight, section); + connection.getRenderer().getRenderWindow().getChunkRenderer().prepareChunkSection(getPosition().getChunkLocation(), sectionHeight, section, chunk); } @Override diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketChunkData.java b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketChunkData.java index 046299329..60b92fbbd 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketChunkData.java +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketChunkData.java @@ -19,6 +19,8 @@ import de.bixilon.minosoft.data.mappings.tweaker.VersionTweaker; import de.bixilon.minosoft.data.world.BlockPosition; import de.bixilon.minosoft.data.world.Chunk; import de.bixilon.minosoft.data.world.ChunkLocation; +import de.bixilon.minosoft.data.world.biome.BiomeAccessor; +import de.bixilon.minosoft.data.world.biome.NoiseBiomeAccessor; import de.bixilon.minosoft.modding.event.events.BlockEntityMetaDataChangeEvent; import de.bixilon.minosoft.modding.event.events.ChunkDataChangeEvent; import de.bixilon.minosoft.protocol.network.Connection; @@ -38,7 +40,6 @@ public class PacketChunkData extends ClientboundPacket { private ChunkLocation location; private Chunk chunk; private CompoundTag heightMap; - private int[] biomes; private boolean ignoreOldData; @Override @@ -84,12 +85,9 @@ public class PacketChunkData extends ClientboundPacket { if (buffer.getVersionId() >= V_18W44A) { this.heightMap = (CompoundTag) buffer.readNBT(); } + BiomeAccessor biomeAccessor = null; if (fullChunk) { - if (buffer.getVersionId() >= V_20W28A) { - this.biomes = buffer.readVarIntArray(); - } else if (buffer.getVersionId() >= V_19W36A) { - this.biomes = buffer.readIntArray(1024); - } + biomeAccessor = new NoiseBiomeAccessor(buffer.readBiomeArray()); } int size = buffer.readVarInt(); @@ -98,6 +96,11 @@ public class PacketChunkData extends ClientboundPacket { if (size > 0) { this.chunk = ChunkUtil.readChunkPacket(buffer, dimension, sectionBitMasks, 0, fullChunk, dimension.getHasSkyLight()); + if (this.chunk != null) { + if (biomeAccessor != null) { + this.chunk.setBiomeAccessor(biomeAccessor); + } + } // set position of the byte buffer, because of some reasons HyPixel makes some weird stuff and sends way to much 0 bytes. (~ 190k), thanks @pokechu22 buffer.setPosition(size + lastPos); } diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketMultiBlockChange.java b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketMultiBlockChange.java index 581ea936e..6cba49c24 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketMultiBlockChange.java +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketMultiBlockChange.java @@ -110,7 +110,7 @@ public class PacketMultiBlockChange extends ClientboundPacket { for (var sectionHeight : sectionHeights) { ChunkSection section = chunk.getSectionOrCreate(sectionHeight); - connection.getRenderer().getRenderWindow().getChunkRenderer().prepareChunkSection(getLocation(), sectionHeight, section); + connection.getRenderer().getRenderWindow().getChunkRenderer().prepareChunkSection(getLocation(), sectionHeight, section, chunk); } } diff --git a/src/main/java/de/bixilon/minosoft/protocol/protocol/InByteBuffer.java b/src/main/java/de/bixilon/minosoft/protocol/protocol/InByteBuffer.java index f8472b017..a84ed7f35 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/protocol/InByteBuffer.java +++ b/src/main/java/de/bixilon/minosoft/protocol/protocol/InByteBuffer.java @@ -26,6 +26,7 @@ import de.bixilon.minosoft.data.entities.Poses; import de.bixilon.minosoft.data.inventory.Slot; import de.bixilon.minosoft.data.mappings.LegacyResourceLocation; import de.bixilon.minosoft.data.mappings.ResourceLocation; +import de.bixilon.minosoft.data.mappings.biomes.Biome; import de.bixilon.minosoft.data.mappings.particle.Particle; import de.bixilon.minosoft.data.mappings.particle.data.BlockParticleData; import de.bixilon.minosoft.data.mappings.particle.data.DustParticleData; @@ -397,6 +398,31 @@ public class InByteBuffer { return ret; } + public Biome[] readBiomeArray() { + int length = 0; + if (this.versionId >= V_20W28A) { + length = readVarInt(); + } else if (this.versionId >= V_19W36A) { + length = 1024; + } + if (length > ProtocolDefinition.PROTOCOL_PACKET_MAX_SIZE) { + throw new IllegalArgumentException("Trying to allocate to much memory"); + } + + Biome[] ret = new Biome[length]; + for (int i = 0; i < length; i++) { + int biomeId; + + if (this.versionId >= V_20W28A) { + biomeId = readVarInt(); + } else { + biomeId = readInt(); + } + ret[i] = this.connection.getMapping().getBiomeRegistry().get(biomeId); + } + return ret; + } + public long[] readLongArray(int length) { if (length > ProtocolDefinition.PROTOCOL_PACKET_MAX_SIZE) { throw new IllegalArgumentException("Trying to allocate to much memory"); diff --git a/src/main/java/de/bixilon/minosoft/util/ChunkUtil.java b/src/main/java/de/bixilon/minosoft/util/ChunkUtil.java index 9bd4160ac..0c73eebc6 100644 --- a/src/main/java/de/bixilon/minosoft/util/ChunkUtil.java +++ b/src/main/java/de/bixilon/minosoft/util/ChunkUtil.java @@ -14,18 +14,21 @@ package de.bixilon.minosoft.util; import de.bixilon.minosoft.data.mappings.Dimension; +import de.bixilon.minosoft.data.mappings.biomes.Biome; import de.bixilon.minosoft.data.mappings.blocks.BlockState; import de.bixilon.minosoft.data.world.BlockInfo; import de.bixilon.minosoft.data.world.Chunk; import de.bixilon.minosoft.data.world.ChunkSection; import de.bixilon.minosoft.data.world.InChunkSectionLocation; +import de.bixilon.minosoft.data.world.biome.BiomeAccessor; +import de.bixilon.minosoft.data.world.biome.DummyBiomeAccessor; +import de.bixilon.minosoft.data.world.biome.XZBiomeAccessor; import de.bixilon.minosoft.data.world.palette.Palette; import de.bixilon.minosoft.protocol.protocol.InByteBuffer; import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition; import java.util.BitSet; import java.util.HashMap; -import java.util.Map; import static de.bixilon.minosoft.protocol.protocol.ProtocolVersions.*; @@ -91,10 +94,10 @@ public final class ChunkUtil { } } } - sectionMap.put(dimension.getLowestSection() + c, new ChunkSection(blockMap, Map.of())); // ToDo + sectionMap.put(dimension.getLowestSection() + c, new ChunkSection(blockMap)); // ToDo } } - return new Chunk(sectionMap); + return new Chunk(sectionMap, new DummyBiomeAccessor(buffer.getConnection().getMapping().getBiomeRegistry().get(0))); } if (buffer.getVersionId() < V_15W35A) { // ToDo: was this really changed in 62? byte sections = BitByte.getBitCount(sectionBitMasks[0]); @@ -138,9 +141,9 @@ public final class ChunkUtil { } } } - sectionMap.put(dimension.getLowestSection() + c, new ChunkSection(blockMap, Map.of())); + sectionMap.put(dimension.getLowestSection() + c, new ChunkSection(blockMap)); } - return new Chunk(sectionMap); + return new Chunk(sectionMap, new DummyBiomeAccessor(buffer.getConnection().getMapping().getBiomeRegistry().get(0))); // ToDo } // really big thanks to: https://wiki.vg/index.php?title=Chunk_Format&oldid=13712 HashMap sectionMap = new HashMap<>(); @@ -201,12 +204,17 @@ public final class ChunkUtil { } } - sectionMap.put(dimension.getLowestSection() + c, new ChunkSection(blockMap, Map.of())); + sectionMap.put(dimension.getLowestSection() + c, new ChunkSection(blockMap)); } - if (buffer.getVersionId() < V_19W36A) { - byte[] biomes = buffer.readBytes(256); + BiomeAccessor biomeAccessor = new DummyBiomeAccessor(buffer.getConnection().getMapping().getBiomeRegistry().get(0)); + if (buffer.getVersionId() < V_19W36A && fullChunk) { + Biome[] biomes = new Biome[256]; + for (int i = 0; i < biomes.length; i++) { + biomes[i] = buffer.getConnection().getMapping().getBiomeRegistry().get(buffer.readInt()); + } + biomeAccessor = new XZBiomeAccessor(biomes); } - return new Chunk(sectionMap); + return new Chunk(sectionMap, biomeAccessor); } public static void readSkyLightPacket(InByteBuffer buffer, long[] skyLightMask, long[] blockLightMask, long[] emptyBlockLightMask, long[] emptySkyLightMask) {