обновленные алгоритмы
This commit is contained in:
@@ -1,12 +1,14 @@
|
||||
package mc.world.anvil;
|
||||
|
||||
import com.flowpowered.nbt.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import mc.core.world.block.Block;
|
||||
import mc.core.world.block.BlockLocation;
|
||||
import mc.core.world.block.BlockType;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Slf4j
|
||||
public class AnvilBlock implements Block {
|
||||
private final AnvilChunkSection chunkSection;
|
||||
private final BlockLocation location;
|
||||
@@ -18,7 +20,9 @@ public class AnvilBlock implements Block {
|
||||
|
||||
@Override
|
||||
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
|
||||
@@ -28,7 +32,7 @@ public class AnvilBlock implements Block {
|
||||
|
||||
@Override
|
||||
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*/);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ public class AnvilChunk implements Chunk {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
AnvilChunk(CompoundTag chunkTag) {
|
||||
log.info(chunkTag.toString());
|
||||
CompoundMap levelTagMap = ((CompoundTag) chunkTag.getValue().get("Level")).getValue();
|
||||
|
||||
this.x = ((IntTag) levelTagMap.get("xPos")).getValue();
|
||||
@@ -50,6 +49,7 @@ public class AnvilChunk implements Chunk {
|
||||
|
||||
@Override
|
||||
public ChunkSection getChunkSection(int height) {
|
||||
if (height > sections.size()-1) return null;
|
||||
return sections.get(height);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +1,27 @@
|
||||
package mc.world.anvil;
|
||||
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import mc.core.world.chunk.Chunk;
|
||||
import mc.core.world.chunk.ChunkProvider;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.nio.file.Paths;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@NoArgsConstructor
|
||||
@Setter
|
||||
public class AnvilChunkProvider implements ChunkProvider {
|
||||
private RegionManager regionManager;
|
||||
|
||||
public AnvilChunkProvider(String mapPath) {
|
||||
this.setRegionManager(new RegionManager(Paths.get(mapPath).resolve("region")));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk getChunk(int x, int z) {
|
||||
log.info("r.{}.{}", x/32, z/32);
|
||||
|
||||
Region region = regionManager.getRegion(x / 32, z / 32);
|
||||
if (region == null) return null;
|
||||
|
||||
|
||||
@@ -42,7 +42,9 @@ public class AnvilChunkSection implements ChunkSection {
|
||||
|
||||
@Override
|
||||
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
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -16,31 +16,14 @@ import java.util.zip.InflaterInputStream;
|
||||
class Region implements Closeable {
|
||||
private static final byte BYTE_TRUE = 1,
|
||||
BYTE_FALSE = 0;
|
||||
private static final byte[] EMPTY_SECTOR = new byte[4096];
|
||||
|
||||
private RandomAccessFile file;
|
||||
private TByteList sectorFree;
|
||||
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 {
|
||||
this.file = new RandomAccessFile(file, "rw");
|
||||
|
||||
//TODO ???
|
||||
correctingSizeRegionFile();
|
||||
|
||||
int sizeOfSectorFree = (int)this.file.length() / 4096;
|
||||
sectorFree = new TByteArrayList(sizeOfSectorFree);
|
||||
|
||||
@@ -50,8 +33,6 @@ class Region implements Closeable {
|
||||
sectorFree.add(BYTE_TRUE);
|
||||
}
|
||||
|
||||
this.file.seek(0L);
|
||||
|
||||
for (int i = 0; i < offsets.length; ++i) {
|
||||
int read = this.file.readInt();
|
||||
offsets[i] = read;
|
||||
@@ -68,7 +49,12 @@ class Region implements Closeable {
|
||||
|
||||
@Nullable
|
||||
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;
|
||||
|
||||
@@ -85,10 +71,8 @@ class Region implements Closeable {
|
||||
boolean gzippedData = (file.readByte() == 0x01);
|
||||
|
||||
if (gzippedData) {
|
||||
log.info("GZipped");
|
||||
log.warn("GZipped");
|
||||
} else {
|
||||
log.info("Inflaten");
|
||||
|
||||
byte[] buffer = new byte[read - 1];
|
||||
file.read(buffer);
|
||||
InflaterInputStream inputStream = new InflaterInputStream(new ByteArrayInputStream(buffer));
|
||||
|
||||
@@ -9,13 +9,18 @@ import org.springframework.lang.Nullable;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
@Slf4j
|
||||
class RegionManager {
|
||||
public class RegionManager {
|
||||
private final Path regionFilesPath;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user