Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support of old MCRegion (.mcr) format #41

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions src/main/java/togos/minecraft/maprend/McRegionChunkData.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package togos.minecraft.maprend;

import java.util.Map;

import org.jnbt.ByteArrayTag;
import org.jnbt.CompoundTag;
import org.jnbt.IntTag;

public class McRegionChunkData extends McRegionMiniChunkData
{
public McRegionChunkData( long px, long py, long pz, int w, int h, int d ) {
super(px,py,pz,w,h,d);
}

/*
public final int height = 128; // Y/+up/-down
public final int depth = 16; // Z/+west/-east
public final int width = 16; // X/+south/-north

(N, -x)
|
|
|
|
(W, +z)--------0---------(E, -z)
|
|
|
|
(S, +x)
*/

public byte[] skyLightData = new byte[(height*depth*width+1)/2];
public byte[] blockLightData = new byte[(height*depth*width+1)/2];
public byte[] lightHeightData = new byte[depth*width];
public boolean terrainPopulated = false;

//// Sky light ////

public void setSkyLight( int x, int y, int z, int value ) {
putNybble(skyLightData, blockIndex(x,y,z), value);
}

//// Light height ////

public void setLightHeight( int x, int z, int height ) {
lightHeightData[z*width+x] = (byte)(height);
}

public static McRegionChunkData fromTag( CompoundTag t ) {
Map m = t.getValue();
IntTag xPos = (IntTag)m.get( "xPos" );
IntTag zPos = (IntTag)m.get( "zPos" );

McRegionChunkData cd = new McRegionChunkData(
16*xPos.getValue().intValue(), 0, 16*zPos.getValue().intValue(),
16, 128, 16
);

cd.blocks = ((ByteArrayTag)m.get("Blocks")).getValue();
cd.block_data = ((ByteArrayTag)m.get("Data")).getValue();
cd.skyLightData = ((ByteArrayTag)m.get("SkyLight")).getValue();
cd.blockLightData = ((ByteArrayTag)m.get("BlockLight")).getValue();
cd.lightHeightData = ((ByteArrayTag)m.get("HeightMap")).getValue();
// TODO: this part
//cd.tileEntityData = ((CompoundTag)m.get("TileEntities")).getValue();
return cd;
}
}
92 changes: 92 additions & 0 deletions src/main/java/togos/minecraft/maprend/McRegionMiniChunkData.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package togos.minecraft.maprend;

import java.util.ArrayList;
import java.util.List;

public class McRegionMiniChunkData
{
/**
* X,Y,Z coordinates (in blocks a.k.a. world units a.k.a. meters)
* of the bottom northeast corner of the chunk within the world.
*/
public final long posX, posY, posZ;
public final int width, height, depth;

public byte[] blocks;
public byte[] block_data;
public List tileEntityData = new ArrayList();

public McRegionMiniChunkData( long px, long py, long pz, int width, int height, int depth ) {
this.posX = px;
this.posY = py;
this.posZ = pz;
this.width = width;
this.height = height;
this.depth = depth;
this.blocks = new byte[height*depth*width];
this.block_data = new byte[(height*depth*width+1)/2];
}

/*
* Return the
* X,Y,Z coordinates (in blocks a.k.a. world units a.k.a. meters)
* of the bottom northeast corner of the chunk within the world.
*/
public long getChunkPositionX() { return posX; }
public long getChunkPositionY() { return posY; }
public long getChunkPositionZ() { return posZ; }

public int getChunkWidth() { return width; }
public int getChunkHeight() { return height; }
public int getChunkDepth() { return depth; }

protected int blockIndex( int x, int y, int z ) {
return y + z*height + x*depth*height;
}

protected void putNybble( byte[] data, int index, int value ) {
int byteIndex = index>>1;
byte oldValue = data[byteIndex];
if( (index & 0x1) == 0 ) {
data[ byteIndex ] = (byte)((oldValue & 0xF0) | (value & 0x0F));
} else {
data[ byteIndex ] = (byte)((oldValue & 0x0F) | ((value<<4) & 0xF0));
}
}

protected byte getNybble( byte[] data, int index ) {
int byteIndex = index>>1;
if( (index & 0x1) == 0 ) {
return (byte)((data[ byteIndex ] >> 4) & 0x0F);
} else {
return (byte)((data[ byteIndex ] >> 0) & 0x0F);
}
}

//// Block ////

public byte getBlock( int x, int y, int z ) {
return blocks[ blockIndex(x,y,z) ];
}

public void setBlockNumber( int x, int y, int z, byte blockNum ) {
blocks[ blockIndex(x,y,z) ] = blockNum;
}

public byte getBlockExtraBits( int x, int y, int z ) {
return getNybble( block_data, blockIndex(x,y,z) );
}

public void setBlockExtraBits( int x, int y, int z, byte value ) {
putNybble( block_data, blockIndex(x,y,z), value );
}

public void setBlock( int x, int y, int z, byte blockNum, byte extraBits ) {
setBlockNumber( x, y, z, blockNum );
setBlockExtraBits( x, y, z, extraBits );
}

public void setBlock( int x, int y, int z, byte blockNum ) {
setBlock( x, y, z, blockNum, (byte)0 );
}
}
31 changes: 26 additions & 5 deletions src/main/java/togos/minecraft/maprend/RegionMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,37 @@ public void addRegion( Region r ) {
if( r.rx >= maxX ) maxX = r.rx+1;
if( r.rz >= maxZ ) maxZ = r.rz+1;
}

static final Pattern rfpat = Pattern.compile("^r\\.(-?\\d+)\\.(-?\\d+)\\.mca$");


private void removeOldRegionFiles() {
int i = regions.size() - 1;
while( i >= 0 ) {
String path = regions.get(i).regionFile.getPath();
int len = path.length();
if( len > 4 && path.regionMatches(len - 4, ".mcr", 0, 4) ) {
regions.remove(i);
if(i < regions.size()) continue;
}
i--;
}
}

static final Pattern rfpat = Pattern.compile("^r\\.(-?[0-9]+)\\.(-?[0-9]+)\\.(mc[ar])$");
static final Pattern arfpat = Pattern.compile("^r\\.(-?[0-9]+)\\.(-?[0-9]+)\\.mca$");

protected void add( File dir, BoundingRect limit ) {
Matcher m;
if( dir.isDirectory() ) {
boolean anvil_only = false;
File[] files = dir.listFiles();
for( int i=0; i<files.length; ++i ) {
m = rfpat.matcher(files[i].getName());
if( m.matches() ) add( files[i], limit );
m = (anvil_only ? arfpat : rfpat).matcher(files[i].getName());
if( m.matches() ) {
if( !anvil_only && m.group(3).equals("mca") ) {
anvil_only = true;
removeOldRegionFiles();
}
add( files[i], limit );
}
}
} else if( (m = rfpat.matcher(dir.getName())).matches() ) {
if( !dir.exists() ) {
Expand Down
Loading