network, rendering: biomes

This commit is contained in:
Bixilon 2021-02-24 18:24:43 +01:00
parent a913ac9674
commit 329f30f644
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
21 changed files with 233 additions and 49 deletions

View File

@ -20,6 +20,7 @@ import java.io.File;
public class StaticConfiguration { 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 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 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 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 public static boolean SKIP_MOJANG_AUTHENTICATION; // disables all connections to mojang

View File

@ -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.entities.entities.vehicle.*
import de.bixilon.minosoft.data.mappings.ResourceLocation import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.data.mappings.blocks.BlockState 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.ProtocolDefinition
import de.bixilon.minosoft.protocol.protocol.ProtocolVersions import de.bixilon.minosoft.protocol.protocol.ProtocolVersions
@ -100,7 +103,7 @@ object VersionTweaker {
section.setBlockInfo(location, null) section.setBlockInfo(location, null)
continue continue
} }
section.setBlockInfo(location, BlockInfo(newBlock, blockInfo.metaData, section.blocksFloatingInfo[location] ?: BlockFloatingInfo())) section.setBlockInfo(location, BlockInfo(newBlock, blockInfo.metaData))
} }
} }
return chunk return chunk

View File

@ -38,7 +38,15 @@ public final class RGBColor implements ChatCode {
if (colorString.startsWith("#")) { if (colorString.startsWith("#")) {
colorString = colorString.substring(1); 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) @IntRange(from = 0, to = 255)
@ -51,16 +59,31 @@ public final class RGBColor implements ChatCode {
return (this.color >>> 24) & 0xFF; return (this.color >>> 24) & 0xFF;
} }
@IntRange(from = 0, to = 1)
public float getFloatRed() {
return getRed() / 255f;
}
@IntRange(from = 0, to = 255) @IntRange(from = 0, to = 255)
public int getGreen() { public int getGreen() {
return (this.color >>> 16) & 0xFF; return (this.color >>> 16) & 0xFF;
} }
@IntRange(from = 0, to = 1)
public float getFloatGreen() {
return getGreen() / 255f;
}
@IntRange(from = 0, to = 255) @IntRange(from = 0, to = 255)
public int getBlue() { public int getBlue() {
return (this.color >>> 8) & 0xFF; return (this.color >>> 8) & 0xFF;
} }
@IntRange(from = 0, to = 1)
public float getFloatBlue() {
return getBlue() / 255f;
}
@Override @Override
public int hashCode() { public int hashCode() {
return this.color; return this.color;
@ -86,8 +109,4 @@ public final class RGBColor implements ChatCode {
public int getColor() { public int getColor() {
return this.color; return this.color;
} }
public static RGBColor noAlpha(int color) {
return new RGBColor(color << 8 | 0xFF);
}
} }

View File

@ -19,7 +19,6 @@ import de.bixilon.minosoft.data.mappings.blocks.BlockState
data class BlockInfo( data class BlockInfo(
val block: BlockState, val block: BlockState,
var metaData: BlockEntityMetaData? = null, var metaData: BlockEntityMetaData? = null,
val info: BlockFloatingInfo = BlockFloatingInfo(),
) { ) {
constructor(block: BlockState) : this(block, null) // ToDo: For java compatibility constructor(block: BlockState) : this(block, null) // ToDo: For java compatibility
} }

View File

@ -13,12 +13,16 @@
package de.bixilon.minosoft.data.world package de.bixilon.minosoft.data.world
import de.bixilon.minosoft.data.mappings.blocks.BlockState import de.bixilon.minosoft.data.mappings.blocks.BlockState
import de.bixilon.minosoft.data.world.biome.BiomeAccessor
import java.util.* import java.util.*
/** /**
* Collection of chunks sections (allocated in y) * Collection of chunks sections (allocated in y)
*/ */
class Chunk(val sections: MutableMap<Int, ChunkSection> = mutableMapOf()) { class Chunk(
val sections: MutableMap<Int, ChunkSection> = mutableMapOf(),
var biomeAccessor: BiomeAccessor,
) {
fun getBlockInfo(location: InChunkLocation): BlockInfo? { fun getBlockInfo(location: InChunkLocation): BlockInfo? {
return sections[location.getSectionHeight()]?.getBlockInfo(location.getInChunkSectionLocation()) return sections[location.getSectionHeight()]?.getBlockInfo(location.getInChunkSectionLocation())
@ -51,7 +55,7 @@ class Chunk(val sections: MutableMap<Int, ChunkSection> = mutableMapOf()) {
it.blocks.remove(inChunkSectionLocation) it.blocks.remove(inChunkSectionLocation)
return return
} }
it.setBlockInfo(inChunkSectionLocation, BlockInfo(block, info = it.blocksFloatingInfo[inChunkSectionLocation] ?: BlockFloatingInfo())) it.setBlockInfo(inChunkSectionLocation, BlockInfo(block))
} }
} }

View File

@ -19,7 +19,6 @@ import de.bixilon.minosoft.data.mappings.blocks.BlockState
*/ */
class ChunkSection constructor( class ChunkSection constructor(
val blocks: MutableMap<InChunkSectionLocation, BlockInfo> = mutableMapOf(), val blocks: MutableMap<InChunkSectionLocation, BlockInfo> = mutableMapOf(),
val blocksFloatingInfo: MutableMap<InChunkSectionLocation, BlockFloatingInfo> = mutableMapOf(),
) { ) {
fun getBlockInfo(location: InChunkSectionLocation): BlockInfo? { fun getBlockInfo(location: InChunkSectionLocation): BlockInfo? {
@ -47,6 +46,6 @@ class ChunkSection constructor(
setBlockInfo(location, null) setBlockInfo(location, null)
return return
} }
setBlockInfo(location, BlockInfo(block, info = blocksFloatingInfo[location] ?: BlockFloatingInfo())) setBlockInfo(location, BlockInfo(block))
} }
} }

View File

@ -22,19 +22,20 @@ import de.bixilon.minosoft.data.mappings.blocks.BlockState;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.HashMap; import java.util.HashMap;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
/** /**
* Collection of chunks * Collection of chunks
*/ */
public class World { public class World {
private final HashMap<ChunkLocation, Chunk> chunks = new HashMap<>(); private final ConcurrentHashMap<ChunkLocation, Chunk> chunks = new ConcurrentHashMap<>();
private final HashBiMap<Integer, Entity> entityIdMap = HashBiMap.create(); private final HashBiMap<Integer, Entity> entityIdMap = HashBiMap.create();
private final HashBiMap<UUID, Entity> entityUUIDMap = HashBiMap.create(); private final HashBiMap<UUID, Entity> entityUUIDMap = HashBiMap.create();
private boolean hardcore; private boolean hardcore;
private boolean raining; private boolean raining;
private Dimension dimension; // used for sky color, etc private Dimension dimension; // used for sky color, etc
public HashMap<ChunkLocation, Chunk> getAllChunks() { public ConcurrentHashMap<ChunkLocation, Chunk> getAllChunks() {
return this.chunks; return this.chunks;
} }

View File

@ -11,12 +11,12 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft. * 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.mappings.biomes.Biome
import de.bixilon.minosoft.data.world.BlockPosition
data class BlockFloatingInfo( interface BiomeAccessor {
var light: Int = 15,
var skyLight: Int = 15, fun getBiome(position: BlockPosition): Biome
var biome: Biome? = null, // ToDo }
)

View File

@ -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 <https://www.gnu.org/licenses/>.
*
* 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
}
}

View File

@ -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 <https://www.gnu.org/licenses/>.
*
* 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<Biome>,
) : 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).
}
}

View File

@ -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 <https://www.gnu.org/licenses/>.
*
* 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<Biome>,
) : BiomeAccessor {
override fun getBiome(position: BlockPosition): Biome {
return biomes[(position.x and 0x0F) or ((position.z and 0x0F) shl 4)]
}
}

View File

@ -29,7 +29,11 @@ import glm_.vec3.Vec3
import kotlin.math.cos import kotlin.math.cos
import kotlin.math.sin 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 mouseSensitivity = Minosoft.getConfig().config.game.camera.moseSensitivity
private var movementSpeed = 7 private var movementSpeed = 7
var cameraPosition = Vec3(0.0f, 0.0f, 0.0f) 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) { for (shader in shaders) {
shader.use().setMat4("viewProjectionMatrix", calculateProjectionMatrix(screenWidth, screenHeight) * calculateViewMatrix()) 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 { private fun calculateProjectionMatrix(screenWidth: Int, screenHeight: Int): Mat4 {

View File

@ -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 <https://www.gnu.org/licenses/>.
*
* 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")
}

View File

@ -20,6 +20,7 @@ import de.bixilon.minosoft.config.key.KeyAction
import de.bixilon.minosoft.config.key.KeyBinding import de.bixilon.minosoft.config.key.KeyBinding
import de.bixilon.minosoft.config.key.KeyCodes import de.bixilon.minosoft.config.key.KeyCodes
import de.bixilon.minosoft.data.mappings.ResourceLocation 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.chunk.ChunkRenderer
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
import de.bixilon.minosoft.gui.rendering.hud.elements.RenderStats import de.bixilon.minosoft.gui.rendering.hud.elements.RenderStats
@ -110,7 +111,7 @@ class RenderWindow(private val connection: Connection, val rendering: Rendering)
glfwTerminate() glfwTerminate()
throw RuntimeException("Failed to create the GLFW window") 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) camera.init(this)
@ -210,7 +211,9 @@ class RenderWindow(private val connection: Connection, val rendering: Rendering)
// Make the window visible // Make the window visible
GL.createCapabilities() GL.createCapabilities()
glClearColor(137 / 256f, 207 / 256f, 240 / 256f, 1.0f)
setSkyColor(RGBColor("#fffe7a"))
glEnable(GL_DEPTH_TEST) glEnable(GL_DEPTH_TEST)
glEnable(GL_BLEND) glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) 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) resourceLocationCallbacks.add(callback)
} }
fun setSkyColor(color: RGBColor) {
glClearColor(color.floatRed, color.floatGreen, color.floatBlue, 1.0f)
}
} }

View File

@ -24,6 +24,7 @@ import de.bixilon.minosoft.gui.rendering.textures.Texture
import de.bixilon.minosoft.gui.rendering.textures.TextureArray import de.bixilon.minosoft.gui.rendering.textures.TextureArray
import de.bixilon.minosoft.protocol.network.Connection import de.bixilon.minosoft.protocol.network.Connection
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import de.bixilon.minosoft.util.logging.Log
import glm_.vec3.Vec3 import glm_.vec3.Vec3
import org.lwjgl.opengl.GL11.GL_CULL_FACE import org.lwjgl.opengl.GL11.GL_CULL_FACE
import org.lwjgl.opengl.GL11.glEnable 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 currentTick = 0 // for animation usage
private var lastTickIncrementTime = 0L 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<Float> = mutableListOf() val data: MutableList<Float> = mutableListOf()
// ToDo: Greedy meshing!
val below = world.allChunks[chunkLocation]?.sections?.get(sectionHeight - 1) val below = world.allChunks[chunkLocation]?.sections?.get(sectionHeight - 1)
val above = 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) //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) 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() return data.toFloatArray()
} }
@ -142,13 +146,13 @@ class ChunkRenderer(private val connection: Connection, private val world: World
fun prepareChunk(chunkLocation: ChunkLocation, chunk: Chunk) { fun prepareChunk(chunkLocation: ChunkLocation, chunk: Chunk) {
chunkSectionsToDraw[chunkLocation] = ConcurrentHashMap() chunkSectionsToDraw[chunkLocation] = ConcurrentHashMap()
for ((sectionHeight, section) in chunk.sections) { 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 { renderWindow.rendering.executor.execute {
val data = prepareChunk(chunkLocation, sectionHeight, section) val data = prepareChunk(chunkLocation, sectionHeight, section, chunk)
var sectionMap = chunkSectionsToDraw[chunkLocation] var sectionMap = chunkSectionsToDraw[chunkLocation]
if (sectionMap == null) { if (sectionMap == null) {

View File

@ -14,7 +14,9 @@
package de.bixilon.minosoft.gui.rendering.chunk.models.renderable package de.bixilon.minosoft.gui.rendering.chunk.models.renderable
import com.google.gson.JsonObject import com.google.gson.JsonObject
import de.bixilon.minosoft.config.StaticConfiguration
import de.bixilon.minosoft.data.Directions 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.text.RGBColor
import de.bixilon.minosoft.data.world.BlockInfo import de.bixilon.minosoft.data.world.BlockInfo
import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModel 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<Float>, neighbourBlocks: Array<BlockInfo?>) { fun render(blockInfo: BlockInfo, biome: Biome, position: Vec3, data: MutableList<Float>, neighbourBlocks: Array<BlockInfo?>) {
val modelMatrix = Mat4().translate(position) val modelMatrix = Mat4().translate(position)
for (direction in Directions.DIRECTIONS) { for (direction in Directions.DIRECTIONS) {
@ -90,8 +92,11 @@ class BlockRenderer(data: JsonObject, parent: BlockModel) {
continue 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) element.render(tintColor, textureMapping, modelMatrix, direction, data)
} }
} }

View File

@ -63,7 +63,7 @@ public class PacketBlockChange extends ClientboundPacket {
section.setRawBlock(getPosition().getInChunkLocation().getInChunkSectionLocation(), getBlock()); 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 @Override

View File

@ -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.BlockPosition;
import de.bixilon.minosoft.data.world.Chunk; import de.bixilon.minosoft.data.world.Chunk;
import de.bixilon.minosoft.data.world.ChunkLocation; 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.BlockEntityMetaDataChangeEvent;
import de.bixilon.minosoft.modding.event.events.ChunkDataChangeEvent; import de.bixilon.minosoft.modding.event.events.ChunkDataChangeEvent;
import de.bixilon.minosoft.protocol.network.Connection; import de.bixilon.minosoft.protocol.network.Connection;
@ -38,7 +40,6 @@ public class PacketChunkData extends ClientboundPacket {
private ChunkLocation location; private ChunkLocation location;
private Chunk chunk; private Chunk chunk;
private CompoundTag heightMap; private CompoundTag heightMap;
private int[] biomes;
private boolean ignoreOldData; private boolean ignoreOldData;
@Override @Override
@ -84,12 +85,9 @@ public class PacketChunkData extends ClientboundPacket {
if (buffer.getVersionId() >= V_18W44A) { if (buffer.getVersionId() >= V_18W44A) {
this.heightMap = (CompoundTag) buffer.readNBT(); this.heightMap = (CompoundTag) buffer.readNBT();
} }
BiomeAccessor biomeAccessor = null;
if (fullChunk) { if (fullChunk) {
if (buffer.getVersionId() >= V_20W28A) { biomeAccessor = new NoiseBiomeAccessor(buffer.readBiomeArray());
this.biomes = buffer.readVarIntArray();
} else if (buffer.getVersionId() >= V_19W36A) {
this.biomes = buffer.readIntArray(1024);
}
} }
int size = buffer.readVarInt(); int size = buffer.readVarInt();
@ -98,6 +96,11 @@ public class PacketChunkData extends ClientboundPacket {
if (size > 0) { if (size > 0) {
this.chunk = ChunkUtil.readChunkPacket(buffer, dimension, sectionBitMasks, 0, fullChunk, dimension.getHasSkyLight()); 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 // 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); buffer.setPosition(size + lastPos);
} }

View File

@ -110,7 +110,7 @@ public class PacketMultiBlockChange extends ClientboundPacket {
for (var sectionHeight : sectionHeights) { for (var sectionHeight : sectionHeights) {
ChunkSection section = chunk.getSectionOrCreate(sectionHeight); ChunkSection section = chunk.getSectionOrCreate(sectionHeight);
connection.getRenderer().getRenderWindow().getChunkRenderer().prepareChunkSection(getLocation(), sectionHeight, section); connection.getRenderer().getRenderWindow().getChunkRenderer().prepareChunkSection(getLocation(), sectionHeight, section, chunk);
} }
} }

View File

@ -26,6 +26,7 @@ import de.bixilon.minosoft.data.entities.Poses;
import de.bixilon.minosoft.data.inventory.Slot; import de.bixilon.minosoft.data.inventory.Slot;
import de.bixilon.minosoft.data.mappings.LegacyResourceLocation; import de.bixilon.minosoft.data.mappings.LegacyResourceLocation;
import de.bixilon.minosoft.data.mappings.ResourceLocation; 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.Particle;
import de.bixilon.minosoft.data.mappings.particle.data.BlockParticleData; import de.bixilon.minosoft.data.mappings.particle.data.BlockParticleData;
import de.bixilon.minosoft.data.mappings.particle.data.DustParticleData; import de.bixilon.minosoft.data.mappings.particle.data.DustParticleData;
@ -397,6 +398,31 @@ public class InByteBuffer {
return ret; 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) { public long[] readLongArray(int length) {
if (length > ProtocolDefinition.PROTOCOL_PACKET_MAX_SIZE) { if (length > ProtocolDefinition.PROTOCOL_PACKET_MAX_SIZE) {
throw new IllegalArgumentException("Trying to allocate to much memory"); throw new IllegalArgumentException("Trying to allocate to much memory");

View File

@ -14,18 +14,21 @@
package de.bixilon.minosoft.util; package de.bixilon.minosoft.util;
import de.bixilon.minosoft.data.mappings.Dimension; 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.mappings.blocks.BlockState;
import de.bixilon.minosoft.data.world.BlockInfo; import de.bixilon.minosoft.data.world.BlockInfo;
import de.bixilon.minosoft.data.world.Chunk; import de.bixilon.minosoft.data.world.Chunk;
import de.bixilon.minosoft.data.world.ChunkSection; import de.bixilon.minosoft.data.world.ChunkSection;
import de.bixilon.minosoft.data.world.InChunkSectionLocation; 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.data.world.palette.Palette;
import de.bixilon.minosoft.protocol.protocol.InByteBuffer; import de.bixilon.minosoft.protocol.protocol.InByteBuffer;
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition; import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition;
import java.util.BitSet; import java.util.BitSet;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map;
import static de.bixilon.minosoft.protocol.protocol.ProtocolVersions.*; 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? if (buffer.getVersionId() < V_15W35A) { // ToDo: was this really changed in 62?
byte sections = BitByte.getBitCount(sectionBitMasks[0]); 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 // really big thanks to: https://wiki.vg/index.php?title=Chunk_Format&oldid=13712
HashMap<Integer, ChunkSection> sectionMap = new HashMap<>(); HashMap<Integer, ChunkSection> 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) { BiomeAccessor biomeAccessor = new DummyBiomeAccessor(buffer.getConnection().getMapping().getBiomeRegistry().get(0));
byte[] biomes = buffer.readBytes(256); 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) { public static void readSkyLightPacket(InByteBuffer buffer, long[] skyLightMask, long[] blockLightMask, long[] emptyBlockLightMask, long[] emptySkyLightMask) {