Archived
0

обновленные алгоритмы

This commit is contained in:
2018-10-22 00:32:25 +03:00
parent b5313723d3
commit 5cca630dfd
9 changed files with 94 additions and 72 deletions

View File

@@ -1,12 +1,14 @@
package mc.world.anvil; package mc.world.anvil;
import com.flowpowered.nbt.Tag; import com.flowpowered.nbt.Tag;
import lombok.extern.slf4j.Slf4j;
import mc.core.world.block.Block; import mc.core.world.block.Block;
import mc.core.world.block.BlockLocation; import mc.core.world.block.BlockLocation;
import mc.core.world.block.BlockType; import mc.core.world.block.BlockType;
import java.util.stream.Stream; import java.util.stream.Stream;
@Slf4j
public class AnvilBlock implements Block { public class AnvilBlock implements Block {
private final AnvilChunkSection chunkSection; private final AnvilChunkSection chunkSection;
private final BlockLocation location; private final BlockLocation location;
@@ -18,7 +20,9 @@ public class AnvilBlock implements Block {
@Override @Override
public int getLight() { public int getLight() {
return chunkSection.getBlockLight().get(((16 * location.getZ()) * location.getY()) + location.getX()); final int idx = (location.getY() << 8 | location.getZ() << 4 | location.getX()) >> 1;
final int value = chunkSection.getBlockLight().get(idx);
return (idx & 1) == 0 ? value & 15 : value >> 4 & 15;
} }
@Override @Override
@@ -28,7 +32,7 @@ public class AnvilBlock implements Block {
@Override @Override
public BlockType getBlockType() { public BlockType getBlockType() {
byte id = chunkSection.getBlocks().get(((16 * location.getZ()) * location.getY()) + location.getX()); byte id = chunkSection.getBlocks().get((location.getY() * 256) + (location.getZ() * 16) + location.getX());
return BlockType.getByIdMeta(id, 0/*FIXME*/); return BlockType.getByIdMeta(id, 0/*FIXME*/);
} }

View File

@@ -22,7 +22,6 @@ public class AnvilChunk implements Chunk {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
AnvilChunk(CompoundTag chunkTag) { AnvilChunk(CompoundTag chunkTag) {
log.info(chunkTag.toString());
CompoundMap levelTagMap = ((CompoundTag) chunkTag.getValue().get("Level")).getValue(); CompoundMap levelTagMap = ((CompoundTag) chunkTag.getValue().get("Level")).getValue();
this.x = ((IntTag) levelTagMap.get("xPos")).getValue(); this.x = ((IntTag) levelTagMap.get("xPos")).getValue();
@@ -50,6 +49,7 @@ public class AnvilChunk implements Chunk {
@Override @Override
public ChunkSection getChunkSection(int height) { public ChunkSection getChunkSection(int height) {
if (height > sections.size()-1) return null;
return sections.get(height); return sections.get(height);
} }

View File

@@ -1,19 +1,27 @@
package mc.world.anvil; package mc.world.anvil;
import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import mc.core.world.chunk.Chunk; import mc.core.world.chunk.Chunk;
import mc.core.world.chunk.ChunkProvider; import mc.core.world.chunk.ChunkProvider;
import org.springframework.stereotype.Component;
import java.nio.file.Paths;
@Slf4j @Slf4j
@Component
@NoArgsConstructor
@Setter @Setter
public class AnvilChunkProvider implements ChunkProvider { public class AnvilChunkProvider implements ChunkProvider {
private RegionManager regionManager; private RegionManager regionManager;
public AnvilChunkProvider(String mapPath) {
this.setRegionManager(new RegionManager(Paths.get(mapPath).resolve("region")));
}
@Override @Override
public Chunk getChunk(int x, int z) { public Chunk getChunk(int x, int z) {
log.info("r.{}.{}", x/32, z/32);
Region region = regionManager.getRegion(x / 32, z / 32); Region region = regionManager.getRegion(x / 32, z / 32);
if (region == null) return null; if (region == null) return null;

View File

@@ -42,7 +42,9 @@ public class AnvilChunkSection implements ChunkSection {
@Override @Override
public int getSkyLight(int x, int y, int z) { public int getSkyLight(int x, int y, int z) {
return skyLight.get(((16 * z) * y) + x); final int idx = (y << 8 | z << 4 | x) >> 1;
final int value = skyLight.get(idx);
return (idx & 1) == 0 ? value & 15 : value >> 4 & 15;
} }
@Override @Override

View File

@@ -1,41 +0,0 @@
package mc.world.anvil;
import com.flowpowered.nbt.CompoundTag;
import com.flowpowered.nbt.Tag;
import com.flowpowered.nbt.stream.NBTInputStream;
import lombok.extern.slf4j.Slf4j;
import mc.core.world.chunk.Chunk;
import mc.core.world.chunk.ChunkProvider;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
@Slf4j
public class Main {
private static LevelInfo buildLevelInfo(Path levelDatPath) throws IOException {
try (NBTInputStream nbtInputStream = new NBTInputStream(new FileInputStream(levelDatPath.toFile()))) {
Tag rootTag = nbtInputStream.readTag();
return new LevelInfo((CompoundTag) rootTag);
}
}
public static void main(String[] args) throws IOException {
final Path worldPath = Paths.get(args[0]);
// level.dat
LevelInfo levelInfo = buildLevelInfo(worldPath.resolve("level.dat"));
log.info(levelInfo.toString());
// regions
RegionManager regionManager = new RegionManager(worldPath.resolve("region"));
AnvilChunkProvider chunkProvider = new AnvilChunkProvider();
chunkProvider.setRegionManager(regionManager);
Chunk chunk = chunkProvider.getChunk(0, 0);
log.info("{}", chunk.getBiome(0,0));
log.info("{}", chunk.getChunkSection(0).getBiome(0,0));
log.info("{}", chunk.getChunkSection(0).getBlock(0,0,0).getBlockType());
}
}

View File

@@ -16,31 +16,14 @@ import java.util.zip.InflaterInputStream;
class Region implements Closeable { class Region implements Closeable {
private static final byte BYTE_TRUE = 1, private static final byte BYTE_TRUE = 1,
BYTE_FALSE = 0; BYTE_FALSE = 0;
private static final byte[] EMPTY_SECTOR = new byte[4096];
private RandomAccessFile file; private RandomAccessFile file;
private TByteList sectorFree; private TByteList sectorFree;
private final int[] offsets = new int[1024]; private final int[] offsets = new int[1024];
private void correctingSizeRegionFile() throws IOException {
if (this.file.length() < 4096L) {
this.file.write(EMPTY_SECTOR);
this.file.write(EMPTY_SECTOR);
}
if ((this.file.length() & 4095L) != 0L) {
for (int i = 0; i < (this.file.length() & 4095L); i++) {
this.file.write(0);
}
}
}
Region(File file) throws IOException { Region(File file) throws IOException {
this.file = new RandomAccessFile(file, "rw"); this.file = new RandomAccessFile(file, "rw");
//TODO ???
correctingSizeRegionFile();
int sizeOfSectorFree = (int)this.file.length() / 4096; int sizeOfSectorFree = (int)this.file.length() / 4096;
sectorFree = new TByteArrayList(sizeOfSectorFree); sectorFree = new TByteArrayList(sizeOfSectorFree);
@@ -50,8 +33,6 @@ class Region implements Closeable {
sectorFree.add(BYTE_TRUE); sectorFree.add(BYTE_TRUE);
} }
this.file.seek(0L);
for (int i = 0; i < offsets.length; ++i) { for (int i = 0; i < offsets.length; ++i) {
int read = this.file.readInt(); int read = this.file.readInt();
offsets[i] = read; offsets[i] = read;
@@ -68,7 +49,12 @@ class Region implements Closeable {
@Nullable @Nullable
Chunk getChunk(int x, int z) { Chunk getChunk(int x, int z) {
int offset = getOffset(x, z); int offset;
try {
offset = getOffset(x, z);
} catch (Exception e) {
return null;
}
if (offset == 0) return null; if (offset == 0) return null;
@@ -85,10 +71,8 @@ class Region implements Closeable {
boolean gzippedData = (file.readByte() == 0x01); boolean gzippedData = (file.readByte() == 0x01);
if (gzippedData) { if (gzippedData) {
log.info("GZipped"); log.warn("GZipped");
} else { } else {
log.info("Inflaten");
byte[] buffer = new byte[read - 1]; byte[] buffer = new byte[read - 1];
file.read(buffer); file.read(buffer);
InflaterInputStream inputStream = new InflaterInputStream(new ByteArrayInputStream(buffer)); InflaterInputStream inputStream = new InflaterInputStream(new ByteArrayInputStream(buffer));

View File

@@ -9,13 +9,18 @@ import org.springframework.lang.Nullable;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths;
@Slf4j @Slf4j
class RegionManager { public class RegionManager {
private final Path regionFilesPath; private final Path regionFilesPath;
private final TIntObjectMap<Region> regions = new TIntObjectHashMap<>(); private final TIntObjectMap<Region> regions = new TIntObjectHashMap<>();
RegionManager(Path regionFilesPath) { public RegionManager(String regionFilesPath) {
this(Paths.get(regionFilesPath));
}
public RegionManager(Path regionFilesPath) {
this.regionFilesPath = regionFilesPath; this.regionFilesPath = regionFilesPath;
} }

View File

@@ -0,0 +1,60 @@
package mc.world.anvil;
import com.google.common.collect.Lists;
import mc.core.world.block.Block;
import mc.core.world.block.BlockType;
import mc.core.world.chunk.Chunk;
import mc.core.world.chunk.ChunkSection;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Paths;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
class RegionTest {
private static Region region;
private static List<BlockType> layersBlock;
@BeforeAll
static void before() throws URISyntaxException, IOException {
region = new Region(Paths.get(RegionTest.class.getResource("/region/r.0.0.mca").toURI()).toFile());
layersBlock = Lists.newArrayList(
BlockType.BEDROCK,
BlockType.DIRT,
BlockType.DIRT,
BlockType.GRASS
);
}
@Test
void getChunk() {
for (int cZ = 0; cZ < 32; cZ++) {
for (int cX = 0; cX < 32; cX++) {
Chunk chunk = region.getChunk(cX, cZ);
assertNotNull(chunk);
ChunkSection chunkSection = chunk.getChunkSection(0);
assertNotNull(chunkSection);
for (int y = 0; y < 16; y++) {
for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) {
Block block = chunkSection.getBlock(x, y, z);
if (y > layersBlock.size()-1) {
assertEquals(BlockType.AIR, block.getBlockType(), String.format("coords: %d %d %d", x+(cX*16), y, z+(cZ*16)));
} else {
assertEquals(layersBlock.get(y), block.getBlockType(), String.format("coords: %d %d %d", x+(cX*16), y, z+(cZ*16)));
}
}
}
}
}
}
}
}

Binary file not shown.