diff --git a/src/main/java/de/bixilon/minosoft/data/Player.java b/src/main/java/de/bixilon/minosoft/data/Player.java deleted file mode 100644 index 588090512..000000000 --- a/src/main/java/de/bixilon/minosoft/data/Player.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Minosoft - * Copyright (C) 2020 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; - -import de.bixilon.minosoft.data.accounts.Account; -import de.bixilon.minosoft.data.entities.entities.player.PlayerEntity; -import de.bixilon.minosoft.data.inventory.Inventory; -import de.bixilon.minosoft.data.inventory.InventoryProperties; -import de.bixilon.minosoft.data.inventory.InventorySlots; -import de.bixilon.minosoft.data.inventory.Slot; -import de.bixilon.minosoft.data.player.PlayerListItem; -import de.bixilon.minosoft.data.scoreboard.ScoreboardManager; -import de.bixilon.minosoft.data.text.ChatComponent; -import de.bixilon.minosoft.data.world.BlockPosition; -import de.bixilon.minosoft.data.world.World; - -import java.util.HashMap; -import java.util.UUID; - -import static de.bixilon.minosoft.protocol.protocol.ProtocolDefinition.PLAYER_INVENTORY_ID; - -public class Player { - public final HashMap playerList = new HashMap<>(); - private final Account account; - private final ScoreboardManager scoreboardManager = new ScoreboardManager(); - private final World world = new World(); - private final HashMap inventories = new HashMap<>(); - private float health; - private int food; - private float saturation; - private BlockPosition spawnPosition; - private GameModes gameMode; - private byte selectedSlot; - private int level; - private int totalExperience; - private PlayerEntity entity; - private boolean spawnConfirmed; - private UUID uuid; - private String playerName; - - private ChatComponent tabHeader = ChatComponent.valueOf(""); - private ChatComponent tabFooter = ChatComponent.valueOf(""); - - public Player(Account account) { - this.account = account; - this.uuid = account.getUUID(); - this.playerName = account.getUsername(); - // create our own inventory without any properties - this.inventories.put(PLAYER_INVENTORY_ID, new Inventory(null)); - } - - public String getPlayerName() { - return this.playerName; - } - - public void setPlayerName(String playerName) { - this.playerName = playerName; - } - - - public UUID getPlayerUUID() { - return this.uuid; - } - - public void setPlayerUUID(UUID uuid) { - this.uuid = uuid; - } - - public Account getAccount() { - return this.account; - } - - public float getHealth() { - return this.health; - } - - public void setHealth(float health) { - this.health = health; - } - - public int getFood() { - return this.food; - } - - public void setFood(int food) { - this.food = food; - } - - public float getSaturation() { - return this.saturation; - } - - public void setSaturation(float saturation) { - this.saturation = saturation; - } - - public BlockPosition getSpawnPosition() { - return this.spawnPosition; - } - - public void setSpawnPosition(BlockPosition spawnPosition) { - this.spawnPosition = spawnPosition; - } - - public GameModes getGameMode() { - return this.gameMode; - } - - public void setGameMode(GameModes gameMode) { - this.gameMode = gameMode; - } - - public World getWorld() { - return this.world; - } - - public byte getSelectedSlot() { - return this.selectedSlot; - } - - public void setSelectedSlot(byte selectedSlot) { - this.selectedSlot = selectedSlot; - } - - public int getLevel() { - return this.level; - } - - public void setLevel(int level) { - this.level = level; - } - - public int getTotalExperience() { - return this.totalExperience; - } - - public void setTotalExperience(int totalExperience) { - this.totalExperience = totalExperience; - } - - public Inventory getPlayerInventory() { - return getInventory(PLAYER_INVENTORY_ID); - } - - public void setPlayerInventory(Slot[] data) { - setInventory(PLAYER_INVENTORY_ID, data); - } - - public void setInventory(int windowId, Slot[] data) { - for (int i = 0; i < data.length; i++) { - setSlot(windowId, i, data[i]); - } - } - - public void setSlot(int windowId, int slot, Slot data) { - this.inventories.get(windowId).setSlot(slot, data); - } - - public Inventory getInventory(int id) { - return this.inventories.get(id); - } - - public Slot getSlot(int windowId, InventorySlots.InventoryInterface slot, int versionId) { - return getSlot(windowId, slot.getId(versionId)); - } - - public Slot getSlot(int windowId, int slot) { - return this.inventories.get(windowId).getSlot(slot); - } - - public void setSlot(int windowId, InventorySlots.InventoryInterface slot, int versionId, Slot data) { - setSlot(windowId, slot.getId(versionId), data); - } - - public void createInventory(InventoryProperties properties) { - this.inventories.put(properties.getWindowId(), new Inventory(properties)); - } - - public void deleteInventory(int windowId) { - this.inventories.remove(windowId); - } - - public boolean isSpawnConfirmed() { - return this.spawnConfirmed; - } - - public void setSpawnConfirmed(boolean spawnConfirmed) { - this.spawnConfirmed = spawnConfirmed; - } - - public ScoreboardManager getScoreboardManager() { - return this.scoreboardManager; - } - - public HashMap getPlayerList() { - return this.playerList; - } - - public PlayerListItem getPlayerListItem(String name) { - // only legacy - for (PlayerListItem listItem : this.playerList.values()) { - if (listItem.getName().equals(name)) { - return listItem; - } - } - return null; - } - - public ChatComponent getTabHeader() { - return this.tabHeader; - } - - public void setTabHeader(ChatComponent tabHeader) { - this.tabHeader = tabHeader; - } - - public ChatComponent getTabFooter() { - return this.tabFooter; - } - - public void setTabFooter(ChatComponent tabFooter) { - this.tabFooter = tabFooter; - } - - public PlayerEntity getEntity() { - return this.entity; - } - - public void setEntity(PlayerEntity entity) { - this.entity = entity; - } -} diff --git a/src/main/java/de/bixilon/minosoft/data/Player.kt b/src/main/java/de/bixilon/minosoft/data/Player.kt new file mode 100644 index 000000000..37c730452 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/data/Player.kt @@ -0,0 +1,104 @@ +/* + * Minosoft + * Copyright (C) 2020 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 + +import de.bixilon.minosoft.data.accounts.Account +import de.bixilon.minosoft.data.entities.entities.player.PlayerEntity +import de.bixilon.minosoft.data.inventory.Inventory +import de.bixilon.minosoft.data.inventory.InventoryProperties +import de.bixilon.minosoft.data.inventory.InventorySlots.InventoryInterface +import de.bixilon.minosoft.data.inventory.Slot +import de.bixilon.minosoft.data.player.PlayerListItem +import de.bixilon.minosoft.data.scoreboard.ScoreboardManager +import de.bixilon.minosoft.data.text.ChatComponent +import de.bixilon.minosoft.data.world.BlockPosition +import de.bixilon.minosoft.data.world.World +import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition +import java.util.* + +class Player(val account: Account) { + val playerList = HashMap() + val scoreboardManager = ScoreboardManager() + val world = World() + private val inventories = HashMap() + var health = 0f + var food = 0 + var saturation = 0f + var spawnPosition: BlockPosition? = null + var gameMode: GameModes? = null + var selectedSlot: Byte = 0 + var level = 0 + var totalExperience = 0 + var entity: PlayerEntity? = null + var isSpawnConfirmed = false + var playerUUID: UUID = account.uuid + var playerName: String = account.username + var tabHeader = ChatComponent.valueOf("")!! + var tabFooter = ChatComponent.valueOf("")!! + + val playerInventory: Inventory? + get() = getInventory(ProtocolDefinition.PLAYER_INVENTORY_ID) + + fun setPlayerInventory(data: Array) { + setInventory(ProtocolDefinition.PLAYER_INVENTORY_ID, data) + } + + fun setInventory(windowId: Int, data: Array) { + for (i in data.indices) { + setSlot(windowId, i, data[i]) + } + } + + fun setSlot(windowId: Int, slot: Int, data: Slot?) { + inventories[windowId]!!.setSlot(slot, data) + } + + fun getInventory(id: Int): Inventory? { + return inventories[id] + } + + fun getSlot(windowId: Int, slot: InventoryInterface, versionId: Int): Slot { + return getSlot(windowId, slot.getId(versionId)) + } + + fun getSlot(windowId: Int, slot: Int): Slot { + return inventories[windowId]!!.getSlot(slot) + } + + fun setSlot(windowId: Int, slot: InventoryInterface, versionId: Int, data: Slot?) { + setSlot(windowId, slot.getId(versionId), data) + } + + fun createInventory(properties: InventoryProperties) { + inventories[properties.windowId] = Inventory(properties) + } + + fun deleteInventory(windowId: Int) { + inventories.remove(windowId) + } + + fun getPlayerListItem(name: String): PlayerListItem? { + // only legacy + for (listItem in playerList.values) { + if (listItem.name == name) { + return listItem + } + } + return null + } + + init { + // create our own inventory without any properties + inventories[ProtocolDefinition.PLAYER_INVENTORY_ID] = Inventory(null) + } +} diff --git a/src/main/java/de/bixilon/minosoft/data/world/BlockPosition.kt b/src/main/java/de/bixilon/minosoft/data/world/BlockPosition.kt index 09cc00468..8f1292795 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/BlockPosition.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/BlockPosition.kt @@ -45,12 +45,15 @@ data class BlockPosition(val x: Int, val y: Int, val z: Int) { return InChunkPosition(x, this.y, z) } - infix operator fun plus(vec3: Vec3): BlockPosition { + infix operator fun plus(vec3: Vec3?): BlockPosition { + if (vec3 == null) { + return this + } return BlockPosition((x + vec3.x).toInt(), (y + vec3.y).toInt(), (z + vec3.z).toInt()) } - operator fun plus(directions: Directions): BlockPosition { - return this + directions.directionVector + infix operator fun plus(directions: Directions?): BlockPosition { + return this + directions?.directionVector } fun getInChunkSectionPosition(): InChunkSectionPosition { diff --git a/src/main/java/de/bixilon/minosoft/data/world/InChunkPosition.kt b/src/main/java/de/bixilon/minosoft/data/world/InChunkPosition.kt index e74ccdbb6..2bb076df0 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/InChunkPosition.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/InChunkPosition.kt @@ -12,6 +12,7 @@ */ package de.bixilon.minosoft.data.world +import de.bixilon.minosoft.data.Directions import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition import glm_.vec3.Vec3 @@ -34,10 +35,17 @@ data class InChunkPosition(val x: Int, val y: Int, val z: Int) { } } - operator fun plus(vec3: Vec3): InChunkPosition { + operator fun plus(vec3: Vec3?): InChunkPosition { + if (vec3 == null) { + return this + } return InChunkPosition((x + vec3.x).toInt(), (y + vec3.y).toInt(), (z + vec3.z).toInt()) } + operator fun plus(direction: Directions?): InChunkPosition { + return this + direction?.directionVector + } + override fun toString(): String { return "($x $y $z)" } diff --git a/src/main/java/de/bixilon/minosoft/data/world/InChunkSectionPosition.kt b/src/main/java/de/bixilon/minosoft/data/world/InChunkSectionPosition.kt index bf9a53988..279e0ad5b 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/InChunkSectionPosition.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/InChunkSectionPosition.kt @@ -55,6 +55,11 @@ data class InChunkSectionPosition(val x: Int, val y: Int, val z: Int) { return InChunkSectionPosition(nextX, nextY, nextZ) } + + fun isEdge(): Boolean { + return x == 0 || y == 0 || z == 0 || x == ProtocolDefinition.SECTION_MAX_X || y == ProtocolDefinition.SECTION_MAX_Y || z == ProtocolDefinition.SECTION_MAX_Z + } + operator fun plus(directions: Directions): InChunkSectionPosition { return this + directions.directionVector } diff --git a/src/main/java/de/bixilon/minosoft/data/world/World.kt b/src/main/java/de/bixilon/minosoft/data/world/World.kt index ec42728a4..565052db3 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/World.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/World.kt @@ -13,10 +13,12 @@ package de.bixilon.minosoft.data.world import com.google.common.collect.HashBiMap +import de.bixilon.minosoft.data.Difficulties import de.bixilon.minosoft.data.entities.block.BlockEntityMetaData import de.bixilon.minosoft.data.entities.entities.Entity import de.bixilon.minosoft.data.mappings.Dimension import de.bixilon.minosoft.data.mappings.blocks.BlockState +import de.bixilon.minosoft.data.world.light.WorldLightAccessor import java.util.* import java.util.concurrent.ConcurrentHashMap @@ -30,7 +32,9 @@ class World { var isHardcore = false var isRaining = false var dimension: Dimension? = null - + var difficulty: Difficulties? = null + var difficultyLocked = false + val worldLightAccessor = WorldLightAccessor(this) fun getBlockInfo(blockPosition: BlockPosition): BlockInfo? { val chunkLocation = blockPosition.getChunkPosition() diff --git a/src/main/java/de/bixilon/minosoft/data/world/light/ChunkLightAccessor.kt b/src/main/java/de/bixilon/minosoft/data/world/light/ChunkLightAccessor.kt index 19deff0a6..cf7669fa1 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/light/ChunkLightAccessor.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/light/ChunkLightAccessor.kt @@ -13,24 +13,28 @@ package de.bixilon.minosoft.data.world.light -import de.bixilon.minosoft.data.Directions import de.bixilon.minosoft.data.world.BlockPosition import de.bixilon.minosoft.data.world.InChunkPosition -import de.bixilon.minosoft.data.world.World class ChunkLightAccessor( - val blockLightLevel: MutableMap = mutableMapOf(), - val skyLightLevel: MutableMap = mutableMapOf(), - val world: World, + private val blockLightLevel: MutableMap> = mutableMapOf(), + private val skyLightLevel: MutableMap> = mutableMapOf(), ) : LightAccessor { - override fun getLightLevel(blockPosition: BlockPosition, direction: Directions): Int { - val inChunkPosition = blockPosition.getInChunkPosition() - val lightLevel = blockLightLevel[inChunkPosition] ?: skyLightLevel[inChunkPosition] + override fun getSkyLight(blockPosition: BlockPosition): Byte { + return skyLightLevel[blockPosition.getSectionHeight()]?.get(blockPosition.getInChunkPosition()) ?: 0 + } - if (lightLevel == null) { - return 1 + override fun getBlockLight(blockPosition: BlockPosition): Byte { + return blockLightLevel[blockPosition.getSectionHeight()]?.get(blockPosition.getInChunkPosition()) ?: 0 + } + + fun merge(chunkLightAccessor: ChunkLightAccessor) { + for ((sectionHeight, section) in chunkLightAccessor.blockLightLevel) { + blockLightLevel[sectionHeight] = section } - return lightLevel.toInt() + for ((sectionHeight, section) in chunkLightAccessor.skyLightLevel) { + skyLightLevel[sectionHeight] = section + } } } diff --git a/src/main/java/de/bixilon/minosoft/data/world/light/DummyLightAccessor.kt b/src/main/java/de/bixilon/minosoft/data/world/light/DummyLightAccessor.kt index 40b0c42c5..cce59c31b 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/light/DummyLightAccessor.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/light/DummyLightAccessor.kt @@ -13,19 +13,15 @@ package de.bixilon.minosoft.data.world.light -import de.bixilon.minosoft.data.Directions import de.bixilon.minosoft.data.world.BlockPosition object DummyLightAccessor : LightAccessor { - - override fun getLightLevel(blockPosition: BlockPosition, direction: Directions): Int { - return when (direction) { - Directions.NORTH -> 5 - Directions.SOUTH -> 7 - Directions.DOWN -> 3 - Directions.UP -> 9 - Directions.WEST -> 11 - Directions.EAST -> 13 - } + override fun getSkyLight(blockPosition: BlockPosition): Byte { + return 15 } + + override fun getBlockLight(blockPosition: BlockPosition): Byte { + return 15 + } + } diff --git a/src/main/java/de/bixilon/minosoft/data/world/light/LightAccessor.kt b/src/main/java/de/bixilon/minosoft/data/world/light/LightAccessor.kt index bf48e6af5..40ac49d3c 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/light/LightAccessor.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/light/LightAccessor.kt @@ -13,10 +13,21 @@ package de.bixilon.minosoft.data.world.light -import de.bixilon.minosoft.data.Directions import de.bixilon.minosoft.data.world.BlockPosition interface LightAccessor { - fun getLightLevel(blockPosition: BlockPosition, direction: Directions): Int + fun getSkyLight(blockPosition: BlockPosition): Byte + + fun getBlockLight(blockPosition: BlockPosition): Byte + + fun getLightLevel(blockPosition: BlockPosition): Byte { + val blockLight = getBlockLight(blockPosition) + val skyLight = getSkyLight(blockPosition) + if (blockLight > skyLight) { + return blockLight + } + return skyLight + } + } diff --git a/src/main/java/de/bixilon/minosoft/data/world/light/WorldLightAccessor.kt b/src/main/java/de/bixilon/minosoft/data/world/light/WorldLightAccessor.kt new file mode 100644 index 000000000..5074acf7f --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/data/world/light/WorldLightAccessor.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.light + +import de.bixilon.minosoft.data.world.BlockPosition +import de.bixilon.minosoft.data.world.World + +class WorldLightAccessor( + private val world: World, +) : LightAccessor { + override fun getSkyLight(blockPosition: BlockPosition): Byte { + return world.chunks[blockPosition.getChunkPosition()]?.lightAccessor?.getSkyLight(blockPosition) ?: 0 + } + + override fun getBlockLight(blockPosition: BlockPosition): Byte { + return world.chunks[blockPosition.getChunkPosition()]?.lightAccessor?.getBlockLight(blockPosition) ?: 0 + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/ChunkMesh.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/ChunkMesh.kt index 34788ebd3..274154d66 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/ChunkMesh.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/ChunkMesh.kt @@ -29,7 +29,7 @@ class ChunkMesh { private var vbo: Int = 0 private var trianglesCount: Int = 0 - fun addVertex(position: Vec3, textureCoordinates: Vec2, texture: Texture, tintColor: RGBColor?, lightLevel: Float = 0.9f) { + fun addVertex(position: Vec3, textureCoordinates: Vec2, texture: Texture, tintColor: RGBColor?, lightLevel: Byte = 14) { data.add(position.x) data.add(position.y) data.add(position.z) @@ -48,7 +48,7 @@ class ChunkMesh { data.add(Float.fromBits(tintColor.color)) } - data.add(lightLevel) + data.add(lightLevel / MAX_LIGHT_LEVEL) } fun load() { @@ -99,5 +99,6 @@ class ChunkMesh { companion object { private const val FLOATS_PER_VERTEX = 11 + private const val MAX_LIGHT_LEVEL = 15f } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/WorldRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/WorldRenderer.kt index 52094a170..8955c778b 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/WorldRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/WorldRenderer.kt @@ -77,7 +77,7 @@ class WorldRenderer(private val connection: Connection, private val world: World blockInfo.block.tintColor?.let { tintColor = it } } - blockInfo.block.getBlockRenderer(blockPosition).render(blockInfo, chunk.lightAccessor!!, tintColor, blockPosition, mesh, neighborBlocks) + blockInfo.block.getBlockRenderer(blockPosition).render(blockInfo, world.worldLightAccessor, tintColor, blockPosition, mesh, neighborBlocks) } return mesh } 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 55542df82..e6f4695ab 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 @@ -92,7 +92,8 @@ class BlockRenderer(data: JsonObject, parent: BlockModel) { continue } - element.render(tintColor, lightAccessor.getLightLevel(position, direction) / 15f, textureMapping, modelMatrix, direction, mesh) + // ToDo: Lightning is determined by cullface attribute + element.render(tintColor, lightAccessor.getLightLevel(position + direction), textureMapping, modelMatrix, direction, mesh) } } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/renderable/ElementRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/renderable/ElementRenderer.kt index ec360f49c..8f2e44590 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/renderable/ElementRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/renderable/ElementRenderer.kt @@ -50,7 +50,7 @@ class ElementRenderer(element: BlockModelElement, rotation: Vec3, uvLock: Boolea } - fun render(tintColor: RGBColor?, lightLevel: Float, textureMapping: MutableMap, modelMatrix: Mat4, direction: Directions, mesh: ChunkMesh) { + fun render(tintColor: RGBColor?, lightLevel: Byte, textureMapping: MutableMap, modelMatrix: Mat4, direction: Directions, mesh: ChunkMesh) { val realDirection = directionMapping[direction]!! val positionTemplate = BlockModelElement.FACE_POSITION_MAP_TEMPLATE[realDirection.ordinal] diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/text/HUDDebugScreenElement.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/text/HUDDebugScreenElement.kt index a7b899cc1..3ec640a2c 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/text/HUDDebugScreenElement.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/text/HUDDebugScreenElement.kt @@ -59,6 +59,15 @@ class HUDDebugScreenElement(private val hudTextElement: HUDTextElement) : HUDTex "Facing ${getFacing()}", "Dimension ${hudTextElement.connection.player.world.dimension}", "Biome ${camera.currentBiome}", + "", + "Difficulty ${hudTextElement.connection.player.world.difficulty?.name?.toLowerCase()}, ${ + if (hudTextElement.connection.player.world.difficultyLocked) { + "locked" + } else { + "unlocked" + } + }", + "Client light: ${hudTextElement.connection.player.world.worldLightAccessor.getLightLevel(camera.blockPosition)} (sky=${hudTextElement.connection.player.world.worldLightAccessor.getSkyLight(camera.blockPosition)}, block=${hudTextElement.connection.player.world.worldLightAccessor.getBlockLight(camera.blockPosition)})" )) chatComponents[FontBindings.RIGHT_UP]!!.addAll(listOf( "Java: ${Runtime.version()} ${System.getProperty("sun.arch.data.model")}bit", @@ -160,7 +169,8 @@ class HUDDebugScreenElement(private val hudTextElement: HUDTextElement) : HUDTex private fun getFacing(): String { val yaw = hudTextElement.renderWindow.camera.yaw val pitch = hudTextElement.renderWindow.camera.pitch - return "${Directions.byDirection(camera.cameraFront).name.toLowerCase()} (${formatRotation(yaw)} / ${formatRotation(pitch)})" + val direction = Directions.byDirection(camera.cameraFront) + return "${Directions.byDirection(camera.cameraFront).name.toLowerCase()} (${direction.directionVector} (${formatRotation(yaw)} / ${formatRotation(pitch)})" } diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketServerDifficulty.java b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketServerDifficulty.java deleted file mode 100644 index c8c220e37..000000000 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketServerDifficulty.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Minosoft - * Copyright (C) 2020 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.protocol.packets.clientbound.play; - -import de.bixilon.minosoft.data.Difficulties; -import de.bixilon.minosoft.protocol.packets.ClientboundPacket; -import de.bixilon.minosoft.protocol.protocol.InByteBuffer; -import de.bixilon.minosoft.util.logging.Log; - -import static de.bixilon.minosoft.protocol.protocol.ProtocolVersions.V_19W11A; - -public class PacketServerDifficulty extends ClientboundPacket { - Difficulties difficulty; - boolean locked; - - @Override - public boolean read(InByteBuffer buffer) { - this.difficulty = Difficulties.byId(buffer.readUnsignedByte()); - if (buffer.getVersionId() > V_19W11A) { - this.locked = buffer.readBoolean(); - } - return true; - } - - @Override - public void log() { - Log.protocol(String.format("[IN] Received server difficulty (difficulty=%s)", this.difficulty)); - } - - public Difficulties getDifficulty() { - return this.difficulty; - } -} diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketServerDifficulty.kt b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketServerDifficulty.kt new file mode 100644 index 000000000..7c5ef0d62 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketServerDifficulty.kt @@ -0,0 +1,42 @@ +/* + * Minosoft + * Copyright (C) 2020 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.protocol.packets.clientbound.play + +import de.bixilon.minosoft.data.Difficulties +import de.bixilon.minosoft.protocol.network.Connection +import de.bixilon.minosoft.protocol.packets.ClientboundPacket +import de.bixilon.minosoft.protocol.protocol.InByteBuffer +import de.bixilon.minosoft.protocol.protocol.ProtocolVersions +import de.bixilon.minosoft.util.logging.Log + +class PacketServerDifficulty : ClientboundPacket() { + lateinit var difficulty: Difficulties + var locked = false + + override fun read(buffer: InByteBuffer): Boolean { + difficulty = Difficulties.byId(buffer.readUnsignedByte().toInt()) + if (buffer.versionId > ProtocolVersions.V_19W11A) { + locked = buffer.readBoolean() + } + return true + } + + override fun handle(connection: Connection) { + connection.player.world.difficulty = difficulty + connection.player.world.difficultyLocked = locked + } + + override fun log() { + Log.protocol("[IN] Received server difficulty (difficulty=$difficulty, locked=${locked})") + } +} diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketUpdateLight.kt b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketUpdateLight.kt index 2b8b50c37..546317a4f 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketUpdateLight.kt +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketUpdateLight.kt @@ -13,6 +13,7 @@ package de.bixilon.minosoft.protocol.packets.clientbound.play import de.bixilon.minosoft.data.world.ChunkPosition +import de.bixilon.minosoft.data.world.light.ChunkLightAccessor import de.bixilon.minosoft.data.world.light.LightAccessor import de.bixilon.minosoft.protocol.network.Connection import de.bixilon.minosoft.protocol.packets.ClientboundPacket @@ -27,7 +28,7 @@ class PacketUpdateLight : ClientboundPacket() { override fun read(buffer: InByteBuffer): Boolean { position = ChunkPosition(buffer.readVarInt(), buffer.readVarInt()) - if (position == ChunkPosition(-1, 21)) { + if (position == ChunkPosition(-6, 20)) { Log.debug("") } if (buffer.versionId >= ProtocolVersions.V_1_16_PRE3) { @@ -61,7 +62,11 @@ class PacketUpdateLight : ClientboundPacket() { override fun handle(connection: Connection) { val chunk = connection.player.world.getOrCreateChunk(position!!) - chunk.lightAccessor = lightAccessor + if (chunk.lightAccessor != null && chunk.lightAccessor is ChunkLightAccessor && lightAccessor is ChunkLightAccessor) { + (chunk.lightAccessor as ChunkLightAccessor).merge(lightAccessor as ChunkLightAccessor) + } else { + chunk.lightAccessor = lightAccessor + } connection.renderer.renderWindow.worldRenderer.prepareChunk(position!!, chunk) } } diff --git a/src/main/java/de/bixilon/minosoft/util/chunk/ChunkUtil.java b/src/main/java/de/bixilon/minosoft/util/chunk/ChunkUtil.java index cf656cf4f..94c36a72d 100644 --- a/src/main/java/de/bixilon/minosoft/util/chunk/ChunkUtil.java +++ b/src/main/java/de/bixilon/minosoft/util/chunk/ChunkUtil.java @@ -60,8 +60,8 @@ public final class ChunkUtil { // parse data int arrayPos = 0; HashMap sectionMap = new HashMap<>(); - for (int c = 0; c < ProtocolDefinition.SECTIONS_PER_CHUNK; c++) { // max sections per chunks in chunk column - if (BitByte.isBitSet(sectionBitMasks[0], c)) { + for (int sectionHeight = dimension.getLowestSection(); sectionHeight < dimension.getHighestSection(); sectionHeight++) { // max sections per chunks in chunk column + if (BitByte.isBitSet(sectionBitMasks[0], sectionHeight)) { HashMap blockMap = new HashMap<>(); for (int nibbleY = 0; nibbleY < ProtocolDefinition.SECTION_HEIGHT_Y; nibbleY++) { @@ -73,13 +73,13 @@ public final class ChunkUtil { if (arrayPos % 2 == 0) { // high bits singleMeta = (byte) (meta[arrayPos / 2] & 0xF); - if (BitByte.isBitSet(addBitMask, c)) { + if (BitByte.isBitSet(addBitMask, sectionHeight)) { singeBlockId = (short) ((singeBlockId << 4) | (addBlockTypes[arrayPos / 2] >>> 4)); } } else { // low 4 bits singleMeta = (byte) ((meta[arrayPos / 2] >>> 4) & 0xF); - if (BitByte.isBitSet(addBitMask, c)) { + if (BitByte.isBitSet(addBitMask, sectionHeight)) { singeBlockId = (short) ((singeBlockId << 4) | (addBlockTypes[arrayPos / 2] & 0xF)); } } @@ -95,7 +95,7 @@ public final class ChunkUtil { } } } - sectionMap.put(dimension.getLowestSection() + c, new ChunkSection(blockMap)); // ToDo + sectionMap.put(dimension.getLowestSection() + sectionHeight, new ChunkSection(blockMap)); // ToDo } } return new ChunkData(sectionMap, new DummyBiomeAccessor(buffer.getConnection().getMapping().getBiomeRegistry().get(0)), DummyLightAccessor.INSTANCE); @@ -122,8 +122,8 @@ public final class ChunkUtil { int arrayPos = 0; HashMap sectionMap = new HashMap<>(); - for (int c = 0; c < ProtocolDefinition.SECTIONS_PER_CHUNK; c++) { // max sections per chunks in chunk column - if (!BitByte.isBitSet(sectionBitMasks[0], c)) { + for (int sectionHeight = dimension.getLowestSection(); sectionHeight < dimension.getHighestSection(); sectionHeight++) { // max sections per chunks in chunk column + if (!BitByte.isBitSet(sectionBitMasks[0], sectionHeight)) { continue; } HashMap blockMap = new HashMap<>(); @@ -142,15 +142,15 @@ public final class ChunkUtil { } } } - sectionMap.put(dimension.getLowestSection() + c, new ChunkSection(blockMap)); + sectionMap.put(dimension.getLowestSection() + sectionHeight, new ChunkSection(blockMap)); } return new ChunkData(sectionMap, new DummyBiomeAccessor(buffer.getConnection().getMapping().getBiomeRegistry().get(0)), DummyLightAccessor.INSTANCE); // ToDo } // really big thanks to: https://wiki.vg/index.php?title=Chunk_Format&oldid=13712 HashMap sectionMap = new HashMap<>(); BitSet sectionBitSet = BitSet.valueOf(sectionBitMasks); - for (int c = 0; c < sectionBitSet.length(); c++) { // max sections per chunks in chunk column - if (!sectionBitSet.get(c)) { + for (int sectionHeight = dimension.getLowestSection(); sectionHeight < sectionBitSet.length(); sectionHeight++) { // max sections per chunks in chunk column + if (!sectionBitSet.get(sectionHeight)) { continue; } if (buffer.getVersionId() >= V_18W43A) { @@ -206,7 +206,7 @@ public final class ChunkUtil { // ToDo } - sectionMap.put(dimension.getLowestSection() + c, new ChunkSection(blockMap)); + sectionMap.put(dimension.getLowestSection() + sectionHeight, new ChunkSection(blockMap)); } ChunkData chunkData = new ChunkData(); chunkData.setBlocks(sectionMap); diff --git a/src/main/java/de/bixilon/minosoft/util/chunk/LightUtil.kt b/src/main/java/de/bixilon/minosoft/util/chunk/LightUtil.kt index fea174001..758e99962 100644 --- a/src/main/java/de/bixilon/minosoft/util/chunk/LightUtil.kt +++ b/src/main/java/de/bixilon/minosoft/util/chunk/LightUtil.kt @@ -16,7 +16,6 @@ package de.bixilon.minosoft.util.chunk import de.bixilon.minosoft.data.mappings.Dimension import de.bixilon.minosoft.data.world.InChunkPosition import de.bixilon.minosoft.data.world.light.ChunkLightAccessor -import de.bixilon.minosoft.data.world.light.DummyLightAccessor import de.bixilon.minosoft.data.world.light.LightAccessor import de.bixilon.minosoft.protocol.protocol.InByteBuffer import de.bixilon.minosoft.protocol.protocol.ProtocolVersions @@ -26,16 +25,16 @@ object LightUtil { fun readLightPacket(buffer: InByteBuffer, skyLightMask: LongArray, blockLightMask: LongArray, emptyBlockLightMask: LongArray, emptySkyLightMask: LongArray, dimension: Dimension): LightAccessor { // ToDo - val blockLight = readLightArray(buffer, BitSet.valueOf(blockLightMask), dimension) - if (!dimension.hasSkyLight) { - return ChunkLightAccessor(blockLight, world = buffer.connection.player.world) + val skyLight = if (dimension.hasSkyLight) { + readLightArray(buffer, BitSet.valueOf(skyLightMask), dimension) + } else { + mutableMapOf() } - val skyLight = readLightArray(buffer, BitSet.valueOf(skyLightMask), dimension) - return DummyLightAccessor - return ChunkLightAccessor(blockLight, skyLight, buffer.connection.player.world) + val blockLight = readLightArray(buffer, BitSet.valueOf(blockLightMask), dimension) + return ChunkLightAccessor(blockLight, skyLight) } - private fun readLightArray(buffer: InByteBuffer, lightMask: BitSet, dimension: Dimension): MutableMap { + private fun readLightArray(buffer: InByteBuffer, lightMask: BitSet, dimension: Dimension): MutableMap> { var highestSectionIndex = dimension.highestSection + 1 val lowesSectionIndex = dimension.lowestSection - 1 if (buffer.versionId >= ProtocolVersions.V_20W49A) { @@ -43,10 +42,11 @@ object LightUtil { highestSectionIndex = lightMask.length() } - val lightLevels: MutableMap = mutableMapOf() + val lightLevels: MutableMap> = mutableMapOf() - for ((arrayIndex, c) in (lowesSectionIndex until highestSectionIndex).withIndex()) { // light sections + for ((arrayIndex, sectionHeight) in (lowesSectionIndex until highestSectionIndex).withIndex()) { // light sections + val currentSectionLightLevel: MutableMap = mutableMapOf() if (!lightMask[arrayIndex]) { continue } @@ -55,12 +55,13 @@ object LightUtil { for (y in 0 until 16) { for (z in 0 until 16) { for (x in 0 until 16 step 2) { - lightLevels[InChunkPosition(x, y + c * 16, z)] = (lightArray[index].toInt() and 0x0F).toByte() - lightLevels[InChunkPosition(x + 1, y + c * 16, z)] = ((lightArray[index].toInt() ushr 4) and 0x0F).toByte() + currentSectionLightLevel[InChunkPosition(x, y + sectionHeight * 16, z)] = (lightArray[index].toInt() and 0x0F).toByte() + currentSectionLightLevel[InChunkPosition(x + 1, y + sectionHeight * 16, z)] = ((lightArray[index].toInt() ushr 4) and 0x0F).toByte() index++ } } } + lightLevels[sectionHeight] = currentSectionLightLevel } return lightLevels }