mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-16 10:55:01 -04:00
change block storage in chunks (wip light, biomes)
This commit is contained in:
parent
5312e0d436
commit
9d5952dd91
@ -1,139 +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.mappings.tweaker;
|
|
||||||
|
|
||||||
import de.bixilon.minosoft.data.entities.EntityMetaData;
|
|
||||||
import de.bixilon.minosoft.data.entities.EntityMetaDataFields;
|
|
||||||
import de.bixilon.minosoft.data.entities.entities.Entity;
|
|
||||||
import de.bixilon.minosoft.data.entities.entities.animal.horse.*;
|
|
||||||
import de.bixilon.minosoft.data.entities.entities.monster.*;
|
|
||||||
import de.bixilon.minosoft.data.entities.entities.vehicle.*;
|
|
||||||
import de.bixilon.minosoft.data.mappings.blocks.Block;
|
|
||||||
import de.bixilon.minosoft.data.world.Chunk;
|
|
||||||
import de.bixilon.minosoft.data.world.ChunkSection;
|
|
||||||
import de.bixilon.minosoft.data.world.InChunkLocation;
|
|
||||||
import de.bixilon.minosoft.data.world.InChunkSectionLocation;
|
|
||||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import static de.bixilon.minosoft.protocol.protocol.ProtocolVersions.V_1_8_9;
|
|
||||||
|
|
||||||
public class VersionTweaker {
|
|
||||||
// some data was packed in mata data in early versions (1.8). This function converts it to the real identifier
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public static Class<? extends Entity> getRealEntityClass(Class<? extends Entity> fakeClass, EntityMetaData metaData, int versionId) {
|
|
||||||
if (fakeClass == ZombiePigman.class) {
|
|
||||||
return ZombifiedPiglin.class;
|
|
||||||
} else if (fakeClass == Zombie.class) {
|
|
||||||
if (versionId > V_1_8_9) { // ToDo: No clue here
|
|
||||||
return fakeClass;
|
|
||||||
}
|
|
||||||
if (metaData.getSets().getInt(EntityMetaDataFields.ZOMBIE_SPECIAL_TYPE) == 1) {
|
|
||||||
return ZombieVillager.class;
|
|
||||||
}
|
|
||||||
} else if (fakeClass == Skeleton.class) {
|
|
||||||
if (versionId > V_1_8_9) { // ToDo: No clue here
|
|
||||||
return fakeClass;
|
|
||||||
}
|
|
||||||
if (metaData.getSets().getInt(EntityMetaDataFields.LEGACY_SKELETON_TYPE) == 1) {
|
|
||||||
return WitherSkeleton.class;
|
|
||||||
}
|
|
||||||
} else if (fakeClass == Guardian.class) {
|
|
||||||
if (versionId > V_1_8_9) { // ToDo: No clue here
|
|
||||||
return fakeClass;
|
|
||||||
}
|
|
||||||
if (metaData.getSets().getBitMask(EntityMetaDataFields.LEGACY_GUARDIAN_FLAGS, 0x02)) {
|
|
||||||
return ElderGuardian.class;
|
|
||||||
}
|
|
||||||
} else if (fakeClass == Horse.class) {
|
|
||||||
if (versionId > V_1_8_9) { // ToDo: No clue here
|
|
||||||
return fakeClass;
|
|
||||||
}
|
|
||||||
return switch (metaData.getSets().getByte(EntityMetaDataFields.LEGACY_HORSE_SPECIAL_TYPE)) {
|
|
||||||
default -> fakeClass;
|
|
||||||
case 1 -> Donkey.class;
|
|
||||||
case 2 -> Mule.class;
|
|
||||||
case 3 -> ZombieHorse.class;
|
|
||||||
case 4 -> SkeletonHorse.class;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
return fakeClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Class<? extends Entity> getRealEntityObjectClass(Class<? extends Entity> fakeClass, int data, int versionId) {
|
|
||||||
if (fakeClass == Minecart.class) {
|
|
||||||
if (versionId > V_1_8_9) { // ToDo: No clue here
|
|
||||||
return fakeClass;
|
|
||||||
}
|
|
||||||
return switch (data) {
|
|
||||||
default -> fakeClass;
|
|
||||||
case 1 -> MinecartChest.class;
|
|
||||||
case 2 -> MinecartFurnace.class;
|
|
||||||
case 3 -> MinecartTNT.class;
|
|
||||||
case 4 -> MinecartSpawner.class;
|
|
||||||
case 5 -> MinecartHopper.class;
|
|
||||||
case 6 -> MinecartCommandBlock.class;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return fakeClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Chunk transformChunk(Chunk chunk, int versionId) {
|
|
||||||
// some blocks need to be tweaked. eg. Grass with a snow block on top becomes snowy grass block
|
|
||||||
if (versionId >= ProtocolDefinition.FLATTING_VERSION_ID) {
|
|
||||||
return chunk;
|
|
||||||
}
|
|
||||||
for (Map.Entry<Integer, ChunkSection> sectionEntry : chunk.getSections().entrySet()) {
|
|
||||||
for (Map.Entry<InChunkSectionLocation, Block> blockEntry : sectionEntry.getValue().getBlocks().entrySet()) {
|
|
||||||
Block newBlock = transformBlock(blockEntry.getValue(), chunk, blockEntry.getKey(), sectionEntry.getKey());
|
|
||||||
if (newBlock == blockEntry.getValue()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
sectionEntry.getValue().setBlock(blockEntry.getKey(), newBlock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return chunk;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Block transformBlock(Block originalBlock, Chunk chunk, InChunkLocation location) {
|
|
||||||
return transformBlock(originalBlock, chunk, location.getInChunkSectionLocation(), (byte) (location.getY() / ProtocolDefinition.SECTION_HEIGHT_Y));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Block transformBlock(Block originalBlock, Chunk chunk, InChunkSectionLocation location, int sectionHeight) {
|
|
||||||
if (originalBlock == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
switch (originalBlock.getIdentifier().getFullIdentifier()) {
|
|
||||||
case "minecraft:grass" -> {
|
|
||||||
Block above = getBlockAbove(chunk, location, sectionHeight);
|
|
||||||
if (above == null) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (above.equals(TweakBlocks.SNOW) || above.equals(TweakBlocks.SNOW_LAYER)) {
|
|
||||||
return TweakBlocks.GRASS_BLOCK_SNOWY_YES;
|
|
||||||
} else {
|
|
||||||
return TweakBlocks.GRASS_BLOCK_SNOWY_NO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// ToDo: all blocks. e.g. doors, etc
|
|
||||||
}
|
|
||||||
return originalBlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Block getBlockAbove(Chunk chunk, InChunkSectionLocation location, int sectionHeight) {
|
|
||||||
return chunk.getBlock(location.getInChunkLocation(sectionHeight));
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,128 @@
|
|||||||
|
/*
|
||||||
|
* 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.mappings.tweaker
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.data.entities.EntityMetaData
|
||||||
|
import de.bixilon.minosoft.data.entities.EntityMetaDataFields
|
||||||
|
import de.bixilon.minosoft.data.entities.entities.Entity
|
||||||
|
import de.bixilon.minosoft.data.entities.entities.animal.horse.*
|
||||||
|
import de.bixilon.minosoft.data.entities.entities.monster.*
|
||||||
|
import de.bixilon.minosoft.data.entities.entities.vehicle.*
|
||||||
|
import de.bixilon.minosoft.data.mappings.blocks.Block
|
||||||
|
import de.bixilon.minosoft.data.world.*
|
||||||
|
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||||
|
import de.bixilon.minosoft.protocol.protocol.ProtocolVersions
|
||||||
|
|
||||||
|
object VersionTweaker {
|
||||||
|
// some data was packed in mata data in early versions (1.8). This function converts it to the real identifier
|
||||||
|
@JvmStatic
|
||||||
|
fun getRealEntityClass(fakeClass: Class<out Entity>, metaData: EntityMetaData, versionId: Int): Class<out Entity> {
|
||||||
|
if (versionId > ProtocolVersions.V_1_8_9) { // ToDo: No clue here
|
||||||
|
return fakeClass
|
||||||
|
}
|
||||||
|
when (fakeClass) {
|
||||||
|
ZombiePigman::class.java -> {
|
||||||
|
return ZombifiedPiglin::class.java
|
||||||
|
}
|
||||||
|
Zombie::class.java -> {
|
||||||
|
if (metaData.sets.getInt(EntityMetaDataFields.ZOMBIE_SPECIAL_TYPE) == 1) {
|
||||||
|
return ZombieVillager::class.java
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Skeleton::class.java -> {
|
||||||
|
if (metaData.sets.getInt(EntityMetaDataFields.LEGACY_SKELETON_TYPE) == 1) {
|
||||||
|
return WitherSkeleton::class.java
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Guardian::class.java -> {
|
||||||
|
if (metaData.sets.getBitMask(EntityMetaDataFields.LEGACY_GUARDIAN_FLAGS, 0x02)) {
|
||||||
|
return ElderGuardian::class.java
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Horse::class.java -> {
|
||||||
|
return when (metaData.sets.getByte(EntityMetaDataFields.LEGACY_HORSE_SPECIAL_TYPE).toInt()) {
|
||||||
|
1 -> Donkey::class.java
|
||||||
|
2 -> Mule::class.java
|
||||||
|
3 -> ZombieHorse::class.java
|
||||||
|
4 -> SkeletonHorse::class.java
|
||||||
|
else -> fakeClass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fakeClass
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getRealEntityObjectClass(fakeClass: Class<out Entity>, data: Int, versionId: Int): Class<out Entity> {
|
||||||
|
if (versionId > ProtocolVersions.V_1_8_9) { // ToDo: No clue here
|
||||||
|
return fakeClass
|
||||||
|
}
|
||||||
|
when (fakeClass) {
|
||||||
|
Minecart::class.java -> {
|
||||||
|
return when (data) {
|
||||||
|
1 -> MinecartChest::class.java
|
||||||
|
2 -> MinecartFurnace::class.java
|
||||||
|
3 -> MinecartTNT::class.java
|
||||||
|
4 -> MinecartSpawner::class.java
|
||||||
|
5 -> MinecartHopper::class.java
|
||||||
|
6 -> MinecartCommandBlock::class.java
|
||||||
|
else -> fakeClass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fakeClass
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun transformChunk(chunk: Chunk, versionId: Int): Chunk {
|
||||||
|
// some blocks need to be tweaked. eg. Grass with a snow block on top becomes snowy grass block
|
||||||
|
if (versionId >= ProtocolDefinition.FLATTING_VERSION_ID) {
|
||||||
|
return chunk
|
||||||
|
}
|
||||||
|
for ((sectionHeight, section) in chunk.sections) {
|
||||||
|
for ((location, blockInfo) in section.blocks) {
|
||||||
|
val newBlock = transformBlock(blockInfo.block, chunk, location, sectionHeight)
|
||||||
|
if (newBlock === blockInfo.block) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (newBlock == null) {
|
||||||
|
section.setBlockInfo(location, null)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
section.setBlockInfo(location, BlockInfo(newBlock, blockInfo.metaData, section.blocksStaticInfo[location] ?: BlockStaticInfo()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return chunk
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun transformBlock(originalBlock: Block, chunk: Chunk, location: InChunkSectionLocation, sectionHeight: Int): Block? {
|
||||||
|
when (originalBlock.identifier.fullIdentifier) {
|
||||||
|
"minecraft:grass" -> {
|
||||||
|
getBlockAbove(chunk, location, sectionHeight)?.let {
|
||||||
|
if (it == TweakBlocks.SNOW || it == TweakBlocks.SNOW_LAYER) {
|
||||||
|
return TweakBlocks.GRASS_BLOCK_SNOWY_YES
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TweakBlocks.GRASS_BLOCK_SNOWY_NO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return originalBlock
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getBlockAbove(chunk: Chunk, location: InChunkSectionLocation, sectionHeight: Int): Block? {
|
||||||
|
val above = location.getInChunkLocation(sectionHeight)
|
||||||
|
return chunk.getBlockInfo(InChunkLocation(above.x, above.y + 1, above.z))?.block
|
||||||
|
}
|
||||||
|
}
|
25
src/main/java/de/bixilon/minosoft/data/world/BlockInfo.kt
Normal file
25
src/main/java/de/bixilon/minosoft/data/world/BlockInfo.kt
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.data.entities.block.BlockEntityMetaData
|
||||||
|
import de.bixilon.minosoft.data.mappings.blocks.Block
|
||||||
|
|
||||||
|
data class BlockInfo(
|
||||||
|
val block: Block,
|
||||||
|
var metaData: BlockEntityMetaData? = null,
|
||||||
|
val info: BlockStaticInfo = BlockStaticInfo(),
|
||||||
|
) {
|
||||||
|
constructor(block: Block) : this(block, null) // ToDo: For java compatibility
|
||||||
|
}
|
@ -45,7 +45,7 @@ data class BlockPosition(val x: Int, val y: Int, val z: Int) {
|
|||||||
|
|
||||||
fun getInChunkSectionLocation(): InChunkSectionLocation {
|
fun getInChunkSectionLocation(): InChunkSectionLocation {
|
||||||
val location = getInChunkLocation()
|
val location = getInChunkLocation()
|
||||||
return InChunkSectionLocation(location.x, this.y % ProtocolDefinition.SECTION_HEIGHT_Y, location.z)
|
return InChunkSectionLocation(location.x, getSectionHeight(), location.z)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getSectionHeight(): Int {
|
fun getSectionHeight(): Int {
|
||||||
|
@ -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.data.world
|
||||||
|
|
||||||
|
data class BlockStaticInfo(
|
||||||
|
var light: Int = 15,
|
||||||
|
var skyLight: Int = 15,
|
||||||
|
// ToDo: Biome
|
||||||
|
)
|
@ -1,99 +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.world;
|
|
||||||
|
|
||||||
import de.bixilon.minosoft.data.entities.block.BlockEntityMetaData;
|
|
||||||
import de.bixilon.minosoft.data.mappings.blocks.Block;
|
|
||||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Collection of 16 chunks sections
|
|
||||||
*/
|
|
||||||
public class Chunk {
|
|
||||||
private final HashMap<Integer, ChunkSection> sections;
|
|
||||||
|
|
||||||
public Chunk(HashMap<Integer, ChunkSection> sections) {
|
|
||||||
this.sections = sections;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Block getBlock(InChunkLocation location) {
|
|
||||||
return getBlock(location.getX(), location.getY(), location.getZ());
|
|
||||||
}
|
|
||||||
|
|
||||||
public Block getBlock(int x, int y, int z) {
|
|
||||||
int section = (y / ProtocolDefinition.SECTION_HEIGHT_Y);
|
|
||||||
if (!this.sections.containsKey(section)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return this.sections.get(section).getBlock(x, y % ProtocolDefinition.SECTION_HEIGHT_Y, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBlock(int x, int y, int z, Block block) {
|
|
||||||
int section = y / ProtocolDefinition.SECTION_HEIGHT_Y;
|
|
||||||
createSection(section);
|
|
||||||
this.sections.get(section).setBlock(x, y % 16, z, block);
|
|
||||||
}
|
|
||||||
|
|
||||||
void createSection(int height) {
|
|
||||||
if (this.sections.get(height) == null) {
|
|
||||||
// section was empty before, creating it
|
|
||||||
this.sections.put(height, new ChunkSection());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBlocks(HashMap<InChunkLocation, Block> blocks) {
|
|
||||||
blocks.forEach(this::setBlock);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBlock(InChunkLocation location, Block block) {
|
|
||||||
int section = (location.getY() / ProtocolDefinition.SECTION_HEIGHT_Y);
|
|
||||||
createSection(section);
|
|
||||||
this.sections.get(section).setBlock(location.getInChunkSectionLocation(), block);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBlockEntityData(InChunkLocation position, BlockEntityMetaData data) {
|
|
||||||
ChunkSection section = this.sections.get((position.getY() / ProtocolDefinition.SECTION_HEIGHT_Y));
|
|
||||||
if (section == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
section.setBlockEntityData(position.getInChunkSectionLocation(), data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BlockEntityMetaData getBlockEntityData(InChunkLocation position) {
|
|
||||||
ChunkSection section = this.sections.get((position.getY() / ProtocolDefinition.SECTION_HEIGHT_Y));
|
|
||||||
if (section == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return section.getBlockEntityData(position.getInChunkSectionLocation());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBlockEntityData(HashMap<InChunkLocation, BlockEntityMetaData> blockEntities) {
|
|
||||||
blockEntities.forEach(this::setBlockEntityData);
|
|
||||||
}
|
|
||||||
|
|
||||||
public HashMap<Integer, ChunkSection> getSections() {
|
|
||||||
return this.sections;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChunkSection getSectionOrCreate(int sectionHeight) {
|
|
||||||
ChunkSection section = this.sections.get(sectionHeight);
|
|
||||||
if (section == null) {
|
|
||||||
section = new ChunkSection();
|
|
||||||
this.sections.put(sectionHeight, section);
|
|
||||||
}
|
|
||||||
return section;
|
|
||||||
}
|
|
||||||
}
|
|
69
src/main/java/de/bixilon/minosoft/data/world/Chunk.kt
Normal file
69
src/main/java/de/bixilon/minosoft/data/world/Chunk.kt
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* 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.world
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.data.mappings.blocks.Block
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collection of chunks sections (allocated in y)
|
||||||
|
*/
|
||||||
|
class Chunk(val sections: MutableMap<Int, ChunkSection> = mutableMapOf()) {
|
||||||
|
|
||||||
|
fun getBlockInfo(location: InChunkLocation): BlockInfo? {
|
||||||
|
return sections[location.getSectionHeight()]?.getBlockInfo(location.getInChunkSectionLocation())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getBlockInfo(x: Int, y: Int, z: Int): BlockInfo? {
|
||||||
|
return getBlockInfo(InChunkLocation(x, y, z))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setBlocks(blocks: HashMap<InChunkLocation, BlockInfo?>) {
|
||||||
|
for ((location, blockInfo) in blocks) {
|
||||||
|
setBlock(location, blockInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setRawBlocks(blocks: HashMap<InChunkLocation, Block?>) {
|
||||||
|
for ((location, blockInfo) in blocks) {
|
||||||
|
setRawBlock(location, blockInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setBlock(location: InChunkLocation, block: BlockInfo?) {
|
||||||
|
getSectionOrCreate(location.getSectionHeight()).setBlockInfo(location.getInChunkSectionLocation(), block)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setRawBlock(location: InChunkLocation, block: Block?) {
|
||||||
|
getSectionOrCreate(location.getSectionHeight()).let {
|
||||||
|
val inChunkSectionLocation = location.getInChunkSectionLocation()
|
||||||
|
if (block == null) {
|
||||||
|
it.blocks.remove(inChunkSectionLocation)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
it.setBlockInfo(inChunkSectionLocation, BlockInfo(block, info = it.blocksStaticInfo[inChunkSectionLocation] ?: BlockStaticInfo()))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getSectionOrCreate(sectionHeight: Int): ChunkSection {
|
||||||
|
return sections[sectionHeight].let {
|
||||||
|
var section = it
|
||||||
|
if (section == null) {
|
||||||
|
section = ChunkSection()
|
||||||
|
sections[sectionHeight] = section
|
||||||
|
}
|
||||||
|
section
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,94 +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.world;
|
|
||||||
|
|
||||||
import de.bixilon.minosoft.data.entities.block.BlockEntityMetaData;
|
|
||||||
import de.bixilon.minosoft.data.mappings.blocks.Block;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Collection of 16x16x16 blocks
|
|
||||||
*/
|
|
||||||
public class ChunkSection {
|
|
||||||
private final HashMap<InChunkSectionLocation, Block> blocks;
|
|
||||||
private final HashMap<InChunkSectionLocation, BlockEntityMetaData> blockEntityMeta = new HashMap<>();
|
|
||||||
private final HashMap<InChunkSectionLocation, Byte> light;
|
|
||||||
private final HashMap<InChunkSectionLocation, Byte> skyLight;
|
|
||||||
|
|
||||||
public ChunkSection(HashMap<InChunkSectionLocation, Block> blocks) {
|
|
||||||
this(blocks, new HashMap<>(), new HashMap<>());
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChunkSection(HashMap<InChunkSectionLocation, Block> blocks, HashMap<InChunkSectionLocation, Byte> light, HashMap<InChunkSectionLocation, Byte> skyLight) {
|
|
||||||
this.blocks = blocks;
|
|
||||||
this.light = light;
|
|
||||||
this.skyLight = skyLight;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChunkSection() {
|
|
||||||
this(new HashMap<>());
|
|
||||||
}
|
|
||||||
|
|
||||||
public Block getBlock(int x, int y, int z) {
|
|
||||||
return getBlock(new InChunkSectionLocation(x, y, z));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Block getBlock(InChunkSectionLocation loc) {
|
|
||||||
return this.blocks.get(loc);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBlock(int x, int y, int z, Block block) {
|
|
||||||
setBlock(new InChunkSectionLocation(x, y, z), block);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBlock(InChunkSectionLocation location, Block block) {
|
|
||||||
if (block == null) {
|
|
||||||
this.blocks.remove(location);
|
|
||||||
this.blockEntityMeta.remove(location);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.blocks.put(location, block);
|
|
||||||
this.blockEntityMeta.remove(location);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBlockEntityData(InChunkSectionLocation position, BlockEntityMetaData data) {
|
|
||||||
// ToDo check if block is really a block entity (command block, spawner, skull, flower pot)
|
|
||||||
this.blockEntityMeta.put(position, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public HashMap<InChunkSectionLocation, Block> getBlocks() {
|
|
||||||
return this.blocks;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HashMap<InChunkSectionLocation, BlockEntityMetaData> getBlockEntityMeta() {
|
|
||||||
return this.blockEntityMeta;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HashMap<InChunkSectionLocation, Byte> getLight() {
|
|
||||||
return this.light;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HashMap<InChunkSectionLocation, Byte> getSkyLight() {
|
|
||||||
return this.skyLight;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BlockEntityMetaData getBlockEntityData(InChunkSectionLocation position) {
|
|
||||||
return this.blockEntityMeta.get(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBlockEntityData(HashMap<InChunkSectionLocation, BlockEntityMetaData> blockEntities) {
|
|
||||||
blockEntities.forEach(this.blockEntityMeta::put);
|
|
||||||
}
|
|
||||||
}
|
|
52
src/main/java/de/bixilon/minosoft/data/world/ChunkSection.kt
Normal file
52
src/main/java/de/bixilon/minosoft/data/world/ChunkSection.kt
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* 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.world
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.data.mappings.blocks.Block
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collection of 16x16x16 blocks
|
||||||
|
*/
|
||||||
|
class ChunkSection constructor(
|
||||||
|
val blocks: MutableMap<InChunkSectionLocation, BlockInfo> = mutableMapOf(),
|
||||||
|
val blocksStaticInfo: MutableMap<InChunkSectionLocation, BlockStaticInfo> = mutableMapOf(),
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun getBlockInfo(location: InChunkSectionLocation): BlockInfo? {
|
||||||
|
return blocks[location]
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setBlockInfo(location: InChunkSectionLocation, blockInfo: BlockInfo?) {
|
||||||
|
if (blockInfo == null) {
|
||||||
|
blocks.remove(location)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
blocks[location] = blockInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getBlockInfo(x: Int, y: Int, z: Int): BlockInfo? {
|
||||||
|
return getBlockInfo(InChunkSectionLocation(x, y, z))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateStaticData() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setRawBlock(location: InChunkSectionLocation, block: Block?) {
|
||||||
|
if (block == null) {
|
||||||
|
setBlockInfo(location, null)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
setBlockInfo(location, BlockInfo(block, info = blocksStaticInfo[location] ?: BlockStaticInfo()))
|
||||||
|
}
|
||||||
|
}
|
@ -30,19 +30,19 @@ public class World {
|
|||||||
private final HashMap<ChunkLocation, Chunk> chunks = new HashMap<>();
|
private final HashMap<ChunkLocation, Chunk> chunks = new HashMap<>();
|
||||||
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();
|
||||||
boolean hardcore;
|
private boolean hardcore;
|
||||||
boolean raining;
|
private boolean raining;
|
||||||
Dimension dimension; // used for sky color, etc
|
private Dimension dimension; // used for sky color, etc
|
||||||
|
|
||||||
public HashMap<ChunkLocation, Chunk> getAllChunks() {
|
public HashMap<ChunkLocation, Chunk> getAllChunks() {
|
||||||
return this.chunks;
|
return this.chunks;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public Block getBlock(BlockPosition pos) {
|
public BlockInfo getBlockInfo(BlockPosition pos) {
|
||||||
ChunkLocation loc = pos.getChunkLocation();
|
ChunkLocation loc = pos.getChunkLocation();
|
||||||
if (getChunk(loc) != null) {
|
if (getChunk(loc) != null) {
|
||||||
return getChunk(loc).getBlock(pos.getInChunkLocation());
|
return getChunk(loc).getBlockInfo(pos.getInChunkLocation());
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -53,7 +53,7 @@ public class World {
|
|||||||
|
|
||||||
public void setBlock(BlockPosition pos, Block block) {
|
public void setBlock(BlockPosition pos, Block block) {
|
||||||
if (getChunk(pos.getChunkLocation()) != null) {
|
if (getChunk(pos.getChunkLocation()) != null) {
|
||||||
getChunk(pos.getChunkLocation()).setBlock(pos.getInChunkLocation(), block);
|
getChunk(pos.getChunkLocation()).setRawBlock(pos.getInChunkLocation(), block);
|
||||||
}
|
}
|
||||||
// do nothing if chunk is unloaded
|
// do nothing if chunk is unloaded
|
||||||
}
|
}
|
||||||
@ -125,16 +125,17 @@ public class World {
|
|||||||
if (chunk == null) {
|
if (chunk == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
chunk.setBlockEntityData(position.getInChunkLocation(), data);
|
var section = chunk.getSections().get(position.getSectionHeight());
|
||||||
|
if (section == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var blockInfo = section.getBlockInfo(position.getInChunkSectionLocation());
|
||||||
|
if (blockInfo == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
blockInfo.setMetaData(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockEntityMetaData getBlockEntityData(BlockPosition position) {
|
|
||||||
Chunk chunk = this.chunks.get(position.getChunkLocation());
|
|
||||||
if (chunk == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return chunk.getBlockEntityData(position.getInChunkLocation());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBlockEntityData(HashMap<BlockPosition, BlockEntityMetaData> blockEntities) {
|
public void setBlockEntityData(HashMap<BlockPosition, BlockEntityMetaData> blockEntities) {
|
||||||
blockEntities.forEach(this::setBlockEntityData);
|
blockEntities.forEach(this::setBlockEntityData);
|
||||||
|
@ -53,38 +53,40 @@ class ChunkRenderer(private val connection: Connection, private val world: World
|
|||||||
val west = world.allChunks[chunkLocation.getLocationByDirection(Directions.WEST)]?.sections?.get(sectionHeight)
|
val west = world.allChunks[chunkLocation.getLocationByDirection(Directions.WEST)]?.sections?.get(sectionHeight)
|
||||||
val east = world.allChunks[chunkLocation.getLocationByDirection(Directions.EAST)]?.sections?.get(sectionHeight)
|
val east = world.allChunks[chunkLocation.getLocationByDirection(Directions.EAST)]?.sections?.get(sectionHeight)
|
||||||
|
|
||||||
for ((position, block) in section.blocks) {
|
for ((position, blockInfo) in section.blocks) {
|
||||||
val blockBelow: Block? = if (position.y == 0 && below != null) {
|
val blockBelow: BlockInfo? = if (position.y == 0 && below != null) {
|
||||||
below.getBlock(position.x, ProtocolDefinition.SECTION_HEIGHT_Y - 1, position.z)
|
below.getBlockInfo(position.x, ProtocolDefinition.SECTION_HEIGHT_Y - 1, position.z)
|
||||||
} else {
|
} else {
|
||||||
section.getBlock(position.getLocationByDirection(Directions.DOWN))
|
section.getBlockInfo(position.getLocationByDirection(Directions.DOWN))
|
||||||
}
|
}
|
||||||
val blockAbove: Block? = if (position.y == ProtocolDefinition.SECTION_HEIGHT_Y - 1 && above != null) {
|
val blockAbove: BlockInfo? = if (position.y == ProtocolDefinition.SECTION_HEIGHT_Y - 1 && above != null) {
|
||||||
above.getBlock(position.x, 0, position.z)
|
above.getBlockInfo(position.x, 0, position.z)
|
||||||
} else {
|
} else {
|
||||||
section.getBlock(position.getLocationByDirection(Directions.UP))
|
section.getBlockInfo(position.getLocationByDirection(Directions.UP))
|
||||||
}
|
}
|
||||||
val blockNorth: Block? = if (position.z == 0 && north != null) {
|
val blockNorth: BlockInfo? = if (position.z == 0 && north != null) {
|
||||||
north.getBlock(position.x, position.y, ProtocolDefinition.SECTION_WIDTH_Z - 1)
|
north.getBlockInfo(position.x, position.y, ProtocolDefinition.SECTION_WIDTH_Z - 1)
|
||||||
} else {
|
} else {
|
||||||
section.getBlock(position.getLocationByDirection(Directions.NORTH))
|
section.getBlockInfo(position.getLocationByDirection(Directions.NORTH))
|
||||||
}
|
}
|
||||||
val blockSouth: Block? = if (position.z == ProtocolDefinition.SECTION_WIDTH_Z - 1 && south != null) {
|
val blockSouth: BlockInfo? = if (position.z == ProtocolDefinition.SECTION_WIDTH_Z - 1 && south != null) {
|
||||||
south.getBlock(position.x, position.y, 0)
|
south.getBlockInfo(position.x, position.y, 0)
|
||||||
} else {
|
} else {
|
||||||
section.getBlock(position.getLocationByDirection(Directions.SOUTH))
|
section.getBlockInfo(position.getLocationByDirection(Directions.SOUTH))
|
||||||
}
|
}
|
||||||
val blockWest: Block? = if (position.x == 0 && west != null) {
|
val blockWest: BlockInfo? = if (position.x == 0 && west != null) {
|
||||||
west.getBlock(ProtocolDefinition.SECTION_WIDTH_X - 1, position.y, position.x)
|
west.getBlockInfo(ProtocolDefinition.SECTION_WIDTH_X - 1, position.y, position.x)
|
||||||
} else {
|
} else {
|
||||||
section.getBlock(position.getLocationByDirection(Directions.WEST))
|
section.getBlockInfo(position.getLocationByDirection(Directions.WEST))
|
||||||
}
|
}
|
||||||
val blockEast: Block? = if (position.x == ProtocolDefinition.SECTION_WIDTH_X - 1 && east != null) {
|
val blockEast: BlockInfo? = if (position.x == ProtocolDefinition.SECTION_WIDTH_X - 1 && east != null) {
|
||||||
east.getBlock(0, position.y, position.z)
|
east.getBlockInfo(0, position.y, position.z)
|
||||||
} else {
|
} else {
|
||||||
section.getBlock(position.getLocationByDirection(Directions.EAST))
|
section.getBlockInfo(position.getLocationByDirection(Directions.EAST))
|
||||||
}
|
}
|
||||||
block.getBlockRenderer(BlockPosition(chunkLocation, sectionHeight, position)).render(Vec3(position.x + chunkLocation.x * ProtocolDefinition.SECTION_WIDTH_X, position.y + sectionHeight * ProtocolDefinition.SECTION_HEIGHT_Y, position.z + chunkLocation.z * ProtocolDefinition.SECTION_WIDTH_Z), data, arrayOf(blockBelow, blockAbove, blockNorth, blockSouth, blockWest, blockEast))
|
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, arrayOf(blockBelow, blockAbove, blockNorth, blockSouth, blockWest, blockEast))
|
||||||
}
|
}
|
||||||
return data.toFloatArray()
|
return data.toFloatArray()
|
||||||
}
|
}
|
||||||
|
@ -57,11 +57,10 @@ public class PacketBlockChange extends ClientboundPacket {
|
|||||||
|
|
||||||
// tweak
|
// tweak
|
||||||
if (!connection.getVersion().isFlattened()) {
|
if (!connection.getVersion().isFlattened()) {
|
||||||
Block block = VersionTweaker.transformBlock(getBlock(), chunk, getPosition().getInChunkLocation());
|
Block block = VersionTweaker.transformBlock(getBlock(), chunk, this.position.getInChunkSectionLocation(), this.position.getSectionHeight());
|
||||||
section.setBlock(getPosition().getInChunkLocation().getInChunkSectionLocation(), block);
|
section.setRawBlock(getPosition().getInChunkLocation().getInChunkSectionLocation(), block);
|
||||||
} else {
|
} else {
|
||||||
Log.debug("Replacing %s with %s", section.getBlock(getPosition().getInChunkLocation().getInChunkSectionLocation()), this.block);
|
section.setRawBlock(getPosition().getInChunkLocation().getInChunkSectionLocation(), getBlock());
|
||||||
section.setBlock(getPosition().getInChunkLocation().getInChunkSectionLocation(), getBlock());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
connection.getRenderer().getRenderWindow().getChunkRenderer().prepareChunkSection(getPosition().getChunkLocation(), sectionHeight, section);
|
connection.getRenderer().getRenderWindow().getChunkRenderer().prepareChunkSection(getPosition().getChunkLocation(), sectionHeight, section);
|
||||||
|
@ -33,7 +33,7 @@ import static de.bixilon.minosoft.protocol.protocol.ProtocolVersions.*;
|
|||||||
|
|
||||||
public class PacketMultiBlockChange extends ClientboundPacket {
|
public class PacketMultiBlockChange extends ClientboundPacket {
|
||||||
private final HashMap<InChunkLocation, Block> blocks = new HashMap<>();
|
private final HashMap<InChunkLocation, Block> blocks = new HashMap<>();
|
||||||
ChunkLocation location;
|
private ChunkLocation location;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean read(InByteBuffer buffer) {
|
public boolean read(InByteBuffer buffer) {
|
||||||
@ -89,16 +89,16 @@ public class PacketMultiBlockChange extends ClientboundPacket {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
connection.fireEvent(new MultiBlockChangeEvent(connection, this));
|
connection.fireEvent(new MultiBlockChangeEvent(connection, this));
|
||||||
chunk.setBlocks(getBlocks());
|
chunk.setRawBlocks(getBlocks());
|
||||||
|
|
||||||
// tweak
|
// tweak
|
||||||
if (!connection.getVersion().isFlattened()) {
|
if (!connection.getVersion().isFlattened()) {
|
||||||
for (Map.Entry<InChunkLocation, Block> entry : getBlocks().entrySet()) {
|
for (Map.Entry<InChunkLocation, Block> entry : getBlocks().entrySet()) {
|
||||||
Block block = VersionTweaker.transformBlock(entry.getValue(), chunk, entry.getKey());
|
Block block = VersionTweaker.transformBlock(entry.getValue(), chunk, entry.getKey().getInChunkSectionLocation(), entry.getKey().getSectionHeight());
|
||||||
if (block == entry.getValue()) {
|
if (block == entry.getValue()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
chunk.setBlock(entry.getKey(), block);
|
chunk.setRawBlock(entry.getKey(), block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ 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.blocks.Block;
|
import de.bixilon.minosoft.data.mappings.blocks.Block;
|
||||||
|
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;
|
||||||
@ -24,6 +25,7 @@ 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.*;
|
||||||
|
|
||||||
@ -56,7 +58,7 @@ public final class ChunkUtil {
|
|||||||
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 c = 0; c < ProtocolDefinition.SECTIONS_PER_CHUNK; c++) { // max sections per chunks in chunk column
|
||||||
if (BitByte.isBitSet(sectionBitMasks[0], c)) {
|
if (BitByte.isBitSet(sectionBitMasks[0], c)) {
|
||||||
HashMap<InChunkSectionLocation, Block> blockMap = new HashMap<>();
|
HashMap<InChunkSectionLocation, BlockInfo> blockMap = new HashMap<>();
|
||||||
|
|
||||||
for (int nibbleY = 0; nibbleY < ProtocolDefinition.SECTION_HEIGHT_Y; nibbleY++) {
|
for (int nibbleY = 0; nibbleY < ProtocolDefinition.SECTION_HEIGHT_Y; nibbleY++) {
|
||||||
for (int nibbleZ = 0; nibbleZ < ProtocolDefinition.SECTION_WIDTH_Z; nibbleZ++) {
|
for (int nibbleZ = 0; nibbleZ < ProtocolDefinition.SECTION_WIDTH_Z; nibbleZ++) {
|
||||||
@ -84,12 +86,12 @@ public final class ChunkUtil {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Block block = buffer.getConnection().getMapping().getBlock(fullBlockId);
|
Block block = buffer.getConnection().getMapping().getBlock(fullBlockId);
|
||||||
blockMap.put(new InChunkSectionLocation(nibbleX, nibbleY, nibbleZ), block);
|
blockMap.put(new InChunkSectionLocation(nibbleX, nibbleY, nibbleZ), new BlockInfo(block));
|
||||||
arrayPos++;
|
arrayPos++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sectionMap.put(dimension.getLowestSection() + c, new ChunkSection(blockMap));
|
sectionMap.put(dimension.getLowestSection() + c, new ChunkSection(blockMap, Map.of())); // ToDo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new Chunk(sectionMap);
|
return new Chunk(sectionMap);
|
||||||
@ -120,7 +122,7 @@ public final class ChunkUtil {
|
|||||||
if (!BitByte.isBitSet(sectionBitMasks[0], c)) {
|
if (!BitByte.isBitSet(sectionBitMasks[0], c)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
HashMap<InChunkSectionLocation, Block> blockMap = new HashMap<>();
|
HashMap<InChunkSectionLocation, BlockInfo> blockMap = new HashMap<>();
|
||||||
|
|
||||||
for (int nibbleY = 0; nibbleY < ProtocolDefinition.SECTION_HEIGHT_Y; nibbleY++) {
|
for (int nibbleY = 0; nibbleY < ProtocolDefinition.SECTION_HEIGHT_Y; nibbleY++) {
|
||||||
for (int nibbleZ = 0; nibbleZ < ProtocolDefinition.SECTION_WIDTH_Z; nibbleZ++) {
|
for (int nibbleZ = 0; nibbleZ < ProtocolDefinition.SECTION_WIDTH_Z; nibbleZ++) {
|
||||||
@ -131,12 +133,12 @@ public final class ChunkUtil {
|
|||||||
arrayPos++;
|
arrayPos++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
blockMap.put(new InChunkSectionLocation(nibbleX, nibbleY, nibbleZ), block);
|
blockMap.put(new InChunkSectionLocation(nibbleX, nibbleY, nibbleZ), new BlockInfo(block));
|
||||||
arrayPos++;
|
arrayPos++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sectionMap.put(dimension.getLowestSection() + c, new ChunkSection(blockMap));
|
sectionMap.put(dimension.getLowestSection() + c, new ChunkSection(blockMap, Map.of()));
|
||||||
}
|
}
|
||||||
return new Chunk(sectionMap);
|
return new Chunk(sectionMap);
|
||||||
}
|
}
|
||||||
@ -156,7 +158,7 @@ public final class ChunkUtil {
|
|||||||
|
|
||||||
long[] data = buffer.readLongArray();
|
long[] data = buffer.readLongArray();
|
||||||
|
|
||||||
HashMap<InChunkSectionLocation, Block> blockMap = new HashMap<>();
|
HashMap<InChunkSectionLocation, BlockInfo> blockMap = new HashMap<>();
|
||||||
for (int nibbleY = 0; nibbleY < ProtocolDefinition.SECTION_HEIGHT_Y; nibbleY++) {
|
for (int nibbleY = 0; nibbleY < ProtocolDefinition.SECTION_HEIGHT_Y; nibbleY++) {
|
||||||
for (int nibbleZ = 0; nibbleZ < ProtocolDefinition.SECTION_WIDTH_Z; nibbleZ++) {
|
for (int nibbleZ = 0; nibbleZ < ProtocolDefinition.SECTION_WIDTH_Z; nibbleZ++) {
|
||||||
for (int nibbleX = 0; nibbleX < ProtocolDefinition.SECTION_WIDTH_X; nibbleX++) {
|
for (int nibbleX = 0; nibbleX < ProtocolDefinition.SECTION_WIDTH_X; nibbleX++) {
|
||||||
@ -187,7 +189,7 @@ public final class ChunkUtil {
|
|||||||
if (block == null) {
|
if (block == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
blockMap.put(new InChunkSectionLocation(nibbleX, nibbleY, nibbleZ), block);
|
blockMap.put(new InChunkSectionLocation(nibbleX, nibbleY, nibbleZ), new BlockInfo(block));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -199,7 +201,7 @@ public final class ChunkUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sectionMap.put(dimension.getLowestSection() + c, new ChunkSection(blockMap));
|
sectionMap.put(dimension.getLowestSection() + c, new ChunkSection(blockMap, Map.of()));
|
||||||
}
|
}
|
||||||
if (buffer.getVersionId() < V_19W36A) {
|
if (buffer.getVersionId() < V_19W36A) {
|
||||||
byte[] biomes = buffer.readBytes(256);
|
byte[] biomes = buffer.readBytes(256);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user