mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-15 18:34:56 -04:00
rendering: proper light
This commit is contained in:
parent
312486cfb4
commit
93c1e32a49
@ -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 <https://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* 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<UUID, PlayerListItem> playerList = new HashMap<>();
|
|
||||||
private final Account account;
|
|
||||||
private final ScoreboardManager scoreboardManager = new ScoreboardManager();
|
|
||||||
private final World world = new World();
|
|
||||||
private final HashMap<Integer, Inventory> 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<UUID, PlayerListItem> 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;
|
|
||||||
}
|
|
||||||
}
|
|
104
src/main/java/de/bixilon/minosoft/data/Player.kt
Normal file
104
src/main/java/de/bixilon/minosoft/data/Player.kt
Normal file
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* 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<UUID, PlayerListItem>()
|
||||||
|
val scoreboardManager = ScoreboardManager()
|
||||||
|
val world = World()
|
||||||
|
private val inventories = HashMap<Int, Inventory>()
|
||||||
|
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<Slot?>) {
|
||||||
|
setInventory(ProtocolDefinition.PLAYER_INVENTORY_ID, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setInventory(windowId: Int, data: Array<Slot?>) {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
@ -45,12 +45,15 @@ data class BlockPosition(val x: Int, val y: Int, val z: Int) {
|
|||||||
return InChunkPosition(x, this.y, z)
|
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())
|
return BlockPosition((x + vec3.x).toInt(), (y + vec3.y).toInt(), (z + vec3.z).toInt())
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun plus(directions: Directions): BlockPosition {
|
infix operator fun plus(directions: Directions?): BlockPosition {
|
||||||
return this + directions.directionVector
|
return this + directions?.directionVector
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getInChunkSectionPosition(): InChunkSectionPosition {
|
fun getInChunkSectionPosition(): InChunkSectionPosition {
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
*/
|
*/
|
||||||
package de.bixilon.minosoft.data.world
|
package de.bixilon.minosoft.data.world
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.data.Directions
|
||||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||||
import glm_.vec3.Vec3
|
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())
|
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 {
|
override fun toString(): String {
|
||||||
return "($x $y $z)"
|
return "($x $y $z)"
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,11 @@ data class InChunkSectionPosition(val x: Int, val y: Int, val z: Int) {
|
|||||||
return InChunkSectionPosition(nextX, nextY, nextZ)
|
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 {
|
operator fun plus(directions: Directions): InChunkSectionPosition {
|
||||||
return this + directions.directionVector
|
return this + directions.directionVector
|
||||||
}
|
}
|
||||||
|
@ -13,10 +13,12 @@
|
|||||||
package de.bixilon.minosoft.data.world
|
package de.bixilon.minosoft.data.world
|
||||||
|
|
||||||
import com.google.common.collect.HashBiMap
|
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.block.BlockEntityMetaData
|
||||||
import de.bixilon.minosoft.data.entities.entities.Entity
|
import de.bixilon.minosoft.data.entities.entities.Entity
|
||||||
import de.bixilon.minosoft.data.mappings.Dimension
|
import de.bixilon.minosoft.data.mappings.Dimension
|
||||||
import de.bixilon.minosoft.data.mappings.blocks.BlockState
|
import de.bixilon.minosoft.data.mappings.blocks.BlockState
|
||||||
|
import de.bixilon.minosoft.data.world.light.WorldLightAccessor
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
|
||||||
@ -30,7 +32,9 @@ class World {
|
|||||||
var isHardcore = false
|
var isHardcore = false
|
||||||
var isRaining = false
|
var isRaining = false
|
||||||
var dimension: Dimension? = null
|
var dimension: Dimension? = null
|
||||||
|
var difficulty: Difficulties? = null
|
||||||
|
var difficultyLocked = false
|
||||||
|
val worldLightAccessor = WorldLightAccessor(this)
|
||||||
|
|
||||||
fun getBlockInfo(blockPosition: BlockPosition): BlockInfo? {
|
fun getBlockInfo(blockPosition: BlockPosition): BlockInfo? {
|
||||||
val chunkLocation = blockPosition.getChunkPosition()
|
val chunkLocation = blockPosition.getChunkPosition()
|
||||||
|
@ -13,24 +13,28 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.data.world.light
|
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.BlockPosition
|
||||||
import de.bixilon.minosoft.data.world.InChunkPosition
|
import de.bixilon.minosoft.data.world.InChunkPosition
|
||||||
import de.bixilon.minosoft.data.world.World
|
|
||||||
|
|
||||||
class ChunkLightAccessor(
|
class ChunkLightAccessor(
|
||||||
val blockLightLevel: MutableMap<InChunkPosition, Byte> = mutableMapOf(),
|
private val blockLightLevel: MutableMap<Int, MutableMap<InChunkPosition, Byte>> = mutableMapOf(),
|
||||||
val skyLightLevel: MutableMap<InChunkPosition, Byte> = mutableMapOf(),
|
private val skyLightLevel: MutableMap<Int, MutableMap<InChunkPosition, Byte>> = mutableMapOf(),
|
||||||
val world: World,
|
|
||||||
) : LightAccessor {
|
) : LightAccessor {
|
||||||
override fun getLightLevel(blockPosition: BlockPosition, direction: Directions): Int {
|
override fun getSkyLight(blockPosition: BlockPosition): Byte {
|
||||||
val inChunkPosition = blockPosition.getInChunkPosition()
|
return skyLightLevel[blockPosition.getSectionHeight()]?.get(blockPosition.getInChunkPosition()) ?: 0
|
||||||
val lightLevel = blockLightLevel[inChunkPosition] ?: skyLightLevel[inChunkPosition]
|
}
|
||||||
|
|
||||||
if (lightLevel == null) {
|
override fun getBlockLight(blockPosition: BlockPosition): Byte {
|
||||||
return 1
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,19 +13,15 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.data.world.light
|
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.BlockPosition
|
||||||
|
|
||||||
object DummyLightAccessor : LightAccessor {
|
object DummyLightAccessor : LightAccessor {
|
||||||
|
override fun getSkyLight(blockPosition: BlockPosition): Byte {
|
||||||
override fun getLightLevel(blockPosition: BlockPosition, direction: Directions): Int {
|
return 15
|
||||||
return when (direction) {
|
|
||||||
Directions.NORTH -> 5
|
|
||||||
Directions.SOUTH -> 7
|
|
||||||
Directions.DOWN -> 3
|
|
||||||
Directions.UP -> 9
|
|
||||||
Directions.WEST -> 11
|
|
||||||
Directions.EAST -> 13
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getBlockLight(blockPosition: BlockPosition): Byte {
|
||||||
|
return 15
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -13,10 +13,21 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.data.world.light
|
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.BlockPosition
|
||||||
|
|
||||||
interface LightAccessor {
|
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
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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.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
|
||||||
|
}
|
||||||
|
}
|
@ -29,7 +29,7 @@ class ChunkMesh {
|
|||||||
private var vbo: Int = 0
|
private var vbo: Int = 0
|
||||||
private var trianglesCount: 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.x)
|
||||||
data.add(position.y)
|
data.add(position.y)
|
||||||
data.add(position.z)
|
data.add(position.z)
|
||||||
@ -48,7 +48,7 @@ class ChunkMesh {
|
|||||||
data.add(Float.fromBits(tintColor.color))
|
data.add(Float.fromBits(tintColor.color))
|
||||||
}
|
}
|
||||||
|
|
||||||
data.add(lightLevel)
|
data.add(lightLevel / MAX_LIGHT_LEVEL)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun load() {
|
fun load() {
|
||||||
@ -99,5 +99,6 @@ class ChunkMesh {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val FLOATS_PER_VERTEX = 11
|
private const val FLOATS_PER_VERTEX = 11
|
||||||
|
private const val MAX_LIGHT_LEVEL = 15f
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,7 @@ class WorldRenderer(private val connection: Connection, private val world: World
|
|||||||
blockInfo.block.tintColor?.let { tintColor = it }
|
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
|
return mesh
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,8 @@ class BlockRenderer(data: JsonObject, parent: BlockModel) {
|
|||||||
continue
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ class ElementRenderer(element: BlockModelElement, rotation: Vec3, uvLock: Boolea
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun render(tintColor: RGBColor?, lightLevel: Float, textureMapping: MutableMap<String, Texture>, modelMatrix: Mat4, direction: Directions, mesh: ChunkMesh) {
|
fun render(tintColor: RGBColor?, lightLevel: Byte, textureMapping: MutableMap<String, Texture>, modelMatrix: Mat4, direction: Directions, mesh: ChunkMesh) {
|
||||||
val realDirection = directionMapping[direction]!!
|
val realDirection = directionMapping[direction]!!
|
||||||
val positionTemplate = BlockModelElement.FACE_POSITION_MAP_TEMPLATE[realDirection.ordinal]
|
val positionTemplate = BlockModelElement.FACE_POSITION_MAP_TEMPLATE[realDirection.ordinal]
|
||||||
|
|
||||||
|
@ -59,6 +59,15 @@ class HUDDebugScreenElement(private val hudTextElement: HUDTextElement) : HUDTex
|
|||||||
"Facing ${getFacing()}",
|
"Facing ${getFacing()}",
|
||||||
"Dimension ${hudTextElement.connection.player.world.dimension}",
|
"Dimension ${hudTextElement.connection.player.world.dimension}",
|
||||||
"Biome ${camera.currentBiome}",
|
"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(
|
chatComponents[FontBindings.RIGHT_UP]!!.addAll(listOf(
|
||||||
"Java: ${Runtime.version()} ${System.getProperty("sun.arch.data.model")}bit",
|
"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 {
|
private fun getFacing(): String {
|
||||||
val yaw = hudTextElement.renderWindow.camera.yaw
|
val yaw = hudTextElement.renderWindow.camera.yaw
|
||||||
val pitch = hudTextElement.renderWindow.camera.pitch
|
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)})"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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 <https://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* 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})")
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,7 @@
|
|||||||
package de.bixilon.minosoft.protocol.packets.clientbound.play
|
package de.bixilon.minosoft.protocol.packets.clientbound.play
|
||||||
|
|
||||||
import de.bixilon.minosoft.data.world.ChunkPosition
|
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.data.world.light.LightAccessor
|
||||||
import de.bixilon.minosoft.protocol.network.Connection
|
import de.bixilon.minosoft.protocol.network.Connection
|
||||||
import de.bixilon.minosoft.protocol.packets.ClientboundPacket
|
import de.bixilon.minosoft.protocol.packets.ClientboundPacket
|
||||||
@ -27,7 +28,7 @@ class PacketUpdateLight : ClientboundPacket() {
|
|||||||
override fun read(buffer: InByteBuffer): Boolean {
|
override fun read(buffer: InByteBuffer): Boolean {
|
||||||
position = ChunkPosition(buffer.readVarInt(), buffer.readVarInt())
|
position = ChunkPosition(buffer.readVarInt(), buffer.readVarInt())
|
||||||
|
|
||||||
if (position == ChunkPosition(-1, 21)) {
|
if (position == ChunkPosition(-6, 20)) {
|
||||||
Log.debug("")
|
Log.debug("")
|
||||||
}
|
}
|
||||||
if (buffer.versionId >= ProtocolVersions.V_1_16_PRE3) {
|
if (buffer.versionId >= ProtocolVersions.V_1_16_PRE3) {
|
||||||
@ -61,7 +62,11 @@ class PacketUpdateLight : ClientboundPacket() {
|
|||||||
|
|
||||||
override fun handle(connection: Connection) {
|
override fun handle(connection: Connection) {
|
||||||
val chunk = connection.player.world.getOrCreateChunk(position!!)
|
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)
|
connection.renderer.renderWindow.worldRenderer.prepareChunk(position!!, chunk)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,8 +60,8 @@ public final class ChunkUtil {
|
|||||||
// parse data
|
// parse data
|
||||||
int arrayPos = 0;
|
int arrayPos = 0;
|
||||||
HashMap<Integer, ChunkSection> sectionMap = new HashMap<>();
|
HashMap<Integer, ChunkSection> sectionMap = new HashMap<>();
|
||||||
for (int c = 0; c < ProtocolDefinition.SECTIONS_PER_CHUNK; c++) { // max sections per chunks in chunk column
|
for (int sectionHeight = dimension.getLowestSection(); sectionHeight < dimension.getHighestSection(); sectionHeight++) { // max sections per chunks in chunk column
|
||||||
if (BitByte.isBitSet(sectionBitMasks[0], c)) {
|
if (BitByte.isBitSet(sectionBitMasks[0], sectionHeight)) {
|
||||||
HashMap<InChunkSectionPosition, BlockInfo> blockMap = new HashMap<>();
|
HashMap<InChunkSectionPosition, BlockInfo> blockMap = new HashMap<>();
|
||||||
|
|
||||||
for (int nibbleY = 0; nibbleY < ProtocolDefinition.SECTION_HEIGHT_Y; nibbleY++) {
|
for (int nibbleY = 0; nibbleY < ProtocolDefinition.SECTION_HEIGHT_Y; nibbleY++) {
|
||||||
@ -73,13 +73,13 @@ public final class ChunkUtil {
|
|||||||
if (arrayPos % 2 == 0) {
|
if (arrayPos % 2 == 0) {
|
||||||
// high bits
|
// high bits
|
||||||
singleMeta = (byte) (meta[arrayPos / 2] & 0xF);
|
singleMeta = (byte) (meta[arrayPos / 2] & 0xF);
|
||||||
if (BitByte.isBitSet(addBitMask, c)) {
|
if (BitByte.isBitSet(addBitMask, sectionHeight)) {
|
||||||
singeBlockId = (short) ((singeBlockId << 4) | (addBlockTypes[arrayPos / 2] >>> 4));
|
singeBlockId = (short) ((singeBlockId << 4) | (addBlockTypes[arrayPos / 2] >>> 4));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// low 4 bits
|
// low 4 bits
|
||||||
singleMeta = (byte) ((meta[arrayPos / 2] >>> 4) & 0xF);
|
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));
|
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);
|
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;
|
int arrayPos = 0;
|
||||||
HashMap<Integer, ChunkSection> sectionMap = new HashMap<>();
|
HashMap<Integer, ChunkSection> sectionMap = new HashMap<>();
|
||||||
for (int c = 0; c < ProtocolDefinition.SECTIONS_PER_CHUNK; c++) { // max sections per chunks in chunk column
|
for (int sectionHeight = dimension.getLowestSection(); sectionHeight < dimension.getHighestSection(); sectionHeight++) { // max sections per chunks in chunk column
|
||||||
if (!BitByte.isBitSet(sectionBitMasks[0], c)) {
|
if (!BitByte.isBitSet(sectionBitMasks[0], sectionHeight)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
HashMap<InChunkSectionPosition, BlockInfo> blockMap = new HashMap<>();
|
HashMap<InChunkSectionPosition, BlockInfo> 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
|
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
|
// 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<>();
|
||||||
BitSet sectionBitSet = BitSet.valueOf(sectionBitMasks);
|
BitSet sectionBitSet = BitSet.valueOf(sectionBitMasks);
|
||||||
for (int c = 0; c < sectionBitSet.length(); c++) { // max sections per chunks in chunk column
|
for (int sectionHeight = dimension.getLowestSection(); sectionHeight < sectionBitSet.length(); sectionHeight++) { // max sections per chunks in chunk column
|
||||||
if (!sectionBitSet.get(c)) {
|
if (!sectionBitSet.get(sectionHeight)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (buffer.getVersionId() >= V_18W43A) {
|
if (buffer.getVersionId() >= V_18W43A) {
|
||||||
@ -206,7 +206,7 @@ public final class ChunkUtil {
|
|||||||
// ToDo
|
// ToDo
|
||||||
}
|
}
|
||||||
|
|
||||||
sectionMap.put(dimension.getLowestSection() + c, new ChunkSection(blockMap));
|
sectionMap.put(dimension.getLowestSection() + sectionHeight, new ChunkSection(blockMap));
|
||||||
}
|
}
|
||||||
ChunkData chunkData = new ChunkData();
|
ChunkData chunkData = new ChunkData();
|
||||||
chunkData.setBlocks(sectionMap);
|
chunkData.setBlocks(sectionMap);
|
||||||
|
@ -16,7 +16,6 @@ package de.bixilon.minosoft.util.chunk
|
|||||||
import de.bixilon.minosoft.data.mappings.Dimension
|
import de.bixilon.minosoft.data.mappings.Dimension
|
||||||
import de.bixilon.minosoft.data.world.InChunkPosition
|
import de.bixilon.minosoft.data.world.InChunkPosition
|
||||||
import de.bixilon.minosoft.data.world.light.ChunkLightAccessor
|
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.data.world.light.LightAccessor
|
||||||
import de.bixilon.minosoft.protocol.protocol.InByteBuffer
|
import de.bixilon.minosoft.protocol.protocol.InByteBuffer
|
||||||
import de.bixilon.minosoft.protocol.protocol.ProtocolVersions
|
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 {
|
fun readLightPacket(buffer: InByteBuffer, skyLightMask: LongArray, blockLightMask: LongArray, emptyBlockLightMask: LongArray, emptySkyLightMask: LongArray, dimension: Dimension): LightAccessor {
|
||||||
// ToDo
|
// ToDo
|
||||||
val blockLight = readLightArray(buffer, BitSet.valueOf(blockLightMask), dimension)
|
val skyLight = if (dimension.hasSkyLight) {
|
||||||
if (!dimension.hasSkyLight) {
|
readLightArray(buffer, BitSet.valueOf(skyLightMask), dimension)
|
||||||
return ChunkLightAccessor(blockLight, world = buffer.connection.player.world)
|
} else {
|
||||||
|
mutableMapOf()
|
||||||
}
|
}
|
||||||
val skyLight = readLightArray(buffer, BitSet.valueOf(skyLightMask), dimension)
|
val blockLight = readLightArray(buffer, BitSet.valueOf(blockLightMask), dimension)
|
||||||
return DummyLightAccessor
|
return ChunkLightAccessor(blockLight, skyLight)
|
||||||
return ChunkLightAccessor(blockLight, skyLight, buffer.connection.player.world)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun readLightArray(buffer: InByteBuffer, lightMask: BitSet, dimension: Dimension): MutableMap<InChunkPosition, Byte> {
|
private fun readLightArray(buffer: InByteBuffer, lightMask: BitSet, dimension: Dimension): MutableMap<Int, MutableMap<InChunkPosition, Byte>> {
|
||||||
var highestSectionIndex = dimension.highestSection + 1
|
var highestSectionIndex = dimension.highestSection + 1
|
||||||
val lowesSectionIndex = dimension.lowestSection - 1
|
val lowesSectionIndex = dimension.lowestSection - 1
|
||||||
if (buffer.versionId >= ProtocolVersions.V_20W49A) {
|
if (buffer.versionId >= ProtocolVersions.V_20W49A) {
|
||||||
@ -43,10 +42,11 @@ object LightUtil {
|
|||||||
highestSectionIndex = lightMask.length()
|
highestSectionIndex = lightMask.length()
|
||||||
}
|
}
|
||||||
|
|
||||||
val lightLevels: MutableMap<InChunkPosition, Byte> = mutableMapOf()
|
val lightLevels: MutableMap<Int, MutableMap<InChunkPosition, Byte>> = mutableMapOf()
|
||||||
|
|
||||||
|
|
||||||
for ((arrayIndex, c) in (lowesSectionIndex until highestSectionIndex).withIndex()) { // light sections
|
for ((arrayIndex, sectionHeight) in (lowesSectionIndex until highestSectionIndex).withIndex()) { // light sections
|
||||||
|
val currentSectionLightLevel: MutableMap<InChunkPosition, Byte> = mutableMapOf()
|
||||||
if (!lightMask[arrayIndex]) {
|
if (!lightMask[arrayIndex]) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -55,12 +55,13 @@ object LightUtil {
|
|||||||
for (y in 0 until 16) {
|
for (y in 0 until 16) {
|
||||||
for (z in 0 until 16) {
|
for (z in 0 until 16) {
|
||||||
for (x in 0 until 16 step 2) {
|
for (x in 0 until 16 step 2) {
|
||||||
lightLevels[InChunkPosition(x, y + c * 16, z)] = (lightArray[index].toInt() and 0x0F).toByte()
|
currentSectionLightLevel[InChunkPosition(x, y + sectionHeight * 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 + 1, y + sectionHeight * 16, z)] = ((lightArray[index].toInt() ushr 4) and 0x0F).toByte()
|
||||||
index++
|
index++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
lightLevels[sectionHeight] = currentSectionLightLevel
|
||||||
}
|
}
|
||||||
return lightLevels
|
return lightLevels
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user