Skip to content

Commit d31ac0c

Browse files
committed
Upload source
1 parent 32e99bd commit d31ac0c

File tree

20 files changed

+2031
-0
lines changed

20 files changed

+2031
-0
lines changed

src/com/ljyloo/PE2PC/PE2PC.java

Lines changed: 286 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,286 @@
1+
package com.ljyloo.PE2PC;
2+
3+
import org.iq80.leveldb.*;
4+
5+
import com.mojang.nbt.CompoundTag;
6+
import com.mojang.nbt.ListTag;
7+
import com.mojang.nbt.NbtIo;
8+
9+
import net.minecraft.world.level.chunk.DataLayer;
10+
import net.minecraft.world.level.chunk.OldDataLayer;
11+
import net.minecraft.world.level.chunk.storage.*;
12+
import static org.iq80.leveldb.impl.Iq80DBFactory.*;
13+
14+
import java.io.*;
15+
import java.util.HashMap;
16+
import java.util.Iterator;
17+
import java.util.Map.Entry;
18+
19+
public class PE2PC {
20+
private final static int DATALAYER_BITS = 7;
21+
private final static int BLOCKDATA_BYTES = 32768;
22+
private final static int METADATA_BYTES = 16384;
23+
private final static int SKYLIGHTDATA_BYTES = 16384;
24+
private final static int BLOCKLIGHTDATA_BYTES = 16384;
25+
26+
public static void main(String[] args) throws IOException {
27+
//System.out.println((-1 % 32 + 32) % 32);
28+
if (args.length != 2) {
29+
printUsageAndExit();
30+
}
31+
32+
File srcFolder;
33+
try {
34+
srcFolder = new File(args[0]);
35+
if (!srcFolder.exists()) {
36+
throw new RuntimeException(args[0] + " doesn't exist");
37+
} else if (!srcFolder.isDirectory()) {
38+
throw new RuntimeException(args[0] + " is not a folder");
39+
}
40+
} catch (Exception e) {
41+
System.err.println("import folder problem: " + e.getMessage());
42+
System.out.println("");
43+
printUsageAndExit();
44+
return;
45+
}
46+
47+
File desFolder;
48+
try {
49+
desFolder = new File(args[0]+"/db");
50+
if (!desFolder.exists()) {
51+
throw new RuntimeException(args[0] + " doesn't exist");
52+
} else if (!desFolder.isDirectory()) {
53+
throw new RuntimeException(args[0] + " is not a folder");
54+
}
55+
} catch (Exception e) {
56+
System.err.println("export folder problem: " + e.getMessage());
57+
System.out.println("");
58+
printUsageAndExit();
59+
return;
60+
}
61+
62+
convert(srcFolder, desFolder);
63+
}
64+
65+
private static void printUsageAndExit() {
66+
System.out.println("Map converter for Minecraft:Pocket Edition, from format \"LevelDB\" to \"Anvil\". (c) ljyloo 2015");
67+
System.out.println("");
68+
System.out.println("Usage:");
69+
System.out.println("\tjava -jar Converter.jar <import folder> <export folder>");
70+
System.out.println("Where:");
71+
System.out.println("\t<import folder>\tThe full path to the folder containing Minecraft:Pocket Edition world");
72+
System.out.println("\t<export folder>\tThe full path to the folder which you want to export");
73+
System.out.println("Example:");
74+
System.out.println("\tjava -jar Converter.jar /home/ljyloo/import /home/ljyloo/export");
75+
System.exit(1);
76+
}
77+
78+
public static void convert(File src, File des) throws IOException{
79+
DB db = null;
80+
try{
81+
Options options = new Options();
82+
options.createIfMissing(true);
83+
db = factory.open(src, options);
84+
85+
DBIterator iterator = db.iterator();
86+
//ArrayList<byte[]> keys = new ArrayList<byte[]>();
87+
HashMap<String, RegionFile> regions = new HashMap<String, RegionFile>();
88+
try{
89+
for(iterator.seekToFirst(); iterator.hasNext(); iterator.next()){
90+
byte[] key = iterator.peekNext().getKey();
91+
if(key.length == 9 && key[8] == 0x30){
92+
byte[] value = iterator.peekNext().getValue();
93+
int chunkX = byteArrayToInt(new byte[]{key[3], key[2], key[1], key[0]});
94+
int chunkZ = byteArrayToInt(new byte[]{key[7], key[6], key[5], key[4]});
95+
System.out.println("Converting chunk X:"+chunkX+" Z:"+chunkZ);
96+
CompoundTag tag = new CompoundTag();
97+
CompoundTag levelData = new CompoundTag();
98+
tag.put("Level", levelData);
99+
100+
levelData.putByte("LightPopulated", (byte)1);
101+
levelData.putByte("TerrainPopulated", (byte)1);
102+
levelData.putByte("V", (byte)1);
103+
levelData.putInt("xPos", chunkX);
104+
levelData.putInt("zPos", chunkZ);
105+
levelData.putLong("InhabitedTime", 0);
106+
levelData.putLong("LastUpdate", 0);
107+
byte[] biomes = new byte[16 * 16];
108+
for(int i = 0; i <256; i++)
109+
biomes[i] = -1;
110+
levelData.putByteArray("Biomes", biomes);
111+
levelData.put("Entities", new ListTag<CompoundTag>("Entities"));
112+
113+
ListTag<CompoundTag> sectionTags = new ListTag<CompoundTag>("Sections");
114+
115+
LevelDBChunk data = new LevelDBChunk(chunkX, chunkZ);
116+
117+
data.blocks = new byte[BLOCKDATA_BYTES];
118+
System.arraycopy(value, 0, data.blocks, 0, BLOCKDATA_BYTES);
119+
120+
byte[] metadata = new byte[METADATA_BYTES];
121+
System.arraycopy(value, BLOCKDATA_BYTES, metadata, 0, METADATA_BYTES);
122+
data.data = new OldDataLayer(metadata, DATALAYER_BITS);
123+
124+
byte[] skyLightData = new byte[SKYLIGHTDATA_BYTES];
125+
System.arraycopy(value, BLOCKDATA_BYTES + METADATA_BYTES, skyLightData, 0, SKYLIGHTDATA_BYTES);
126+
data.skyLight = new OldDataLayer(skyLightData, DATALAYER_BITS);
127+
128+
byte[] blockLightData = new byte[BLOCKLIGHTDATA_BYTES];
129+
System.arraycopy(value, BLOCKDATA_BYTES + METADATA_BYTES + SKYLIGHTDATA_BYTES, blockLightData, 0, BLOCKLIGHTDATA_BYTES);
130+
data.blockLight = new OldDataLayer(blockLightData, DATALAYER_BITS);
131+
132+
for (int yBase = 0; yBase < (128 / 16); yBase++) {
133+
134+
// find non-air
135+
boolean allAir = true;
136+
for (int x = 0; x < 16 && allAir; x++) {
137+
for (int y = 0; y < 16 && allAir; y++) {
138+
for (int z = 0; z < 16; z++) {
139+
int pos = (x << 11) | (z << 7) | (y + (yBase << 4));
140+
int block = data.blocks[pos];
141+
if (block != 0) {
142+
allAir = false;
143+
break;
144+
}
145+
}
146+
}
147+
}
148+
149+
if (allAir) {
150+
continue;
151+
}
152+
153+
// build section
154+
byte[] blocks = new byte[16 * 16 * 16];
155+
DataLayer dataValues = new DataLayer(blocks.length, 4);
156+
DataLayer skyLight = new DataLayer(blocks.length, 4);
157+
DataLayer blockLight = new DataLayer(blocks.length, 4);
158+
159+
for (int x = 0; x < 16; x++) {
160+
for (int y = 0; y < 16; y++) {
161+
for (int z = 0; z < 16; z++) {
162+
int pos = (x << 11) | (z << 7) | (y + (yBase << 4));
163+
int block = data.blocks[pos];
164+
165+
blocks[(y << 8) | (z << 4) | x] = (byte) (block & 0xff);
166+
dataValues.set(x, y, z, data.data.get(x, y + (yBase << 4), z));
167+
skyLight.set(x, y, z, data.skyLight.get(x, y + (yBase << 4), z));
168+
blockLight.set(x, y, z, data.blockLight.get(x, y + (yBase << 4), z));
169+
}
170+
}
171+
}
172+
173+
CompoundTag sectionTag = new CompoundTag();
174+
175+
sectionTag.putByte("Y", (byte) (yBase & 0xff));
176+
sectionTag.putByteArray("Blocks", blocks);
177+
sectionTag.putByteArray("Data", dataValues.data);
178+
sectionTag.putByteArray("SkyLight", skyLight.data);
179+
sectionTag.putByteArray("BlockLight", blockLight.data);
180+
181+
sectionTags.add(sectionTag);
182+
}
183+
levelData.put("Sections", sectionTags);
184+
185+
levelData.put("TileEntities", new ListTag<CompoundTag>("TileEntities"));
186+
int[] heightMap = new int[256];
187+
for(int x = 0; x < 16; x++){
188+
for(int z = 0; z < 16; z++){
189+
for(int y = 127; y >= 0; y--){
190+
int pos = (x << 11) | (z << 7) | y;
191+
int block = data.blocks[pos];
192+
if(block != 0){
193+
heightMap[(x << 4) | z] = y;
194+
break;
195+
}
196+
}
197+
}
198+
}
199+
levelData.putIntArray("HeightMap", heightMap);
200+
201+
String k = (chunkX >> 5) + "." + (chunkZ >> 5);
202+
if(!regions.containsKey(k)){
203+
regions.put(k, new RegionFile(new File(des, "r." + (chunkX >> 5) + "." + (chunkZ >> 5) + ".mca")));
204+
}
205+
RegionFile regionDest = regions.get(k);
206+
int regionX = (chunkX % 32 + 32) % 32;
207+
int regionZ = (chunkZ % 32 + 32) % 32;
208+
/*if(chunkX < 0 || chunkZ < 0){
209+
@SuppressWarnings("unused")
210+
int i = 1+1;
211+
}*/
212+
DataOutputStream chunkDataOutputStream = regionDest.getChunkDataOutputStream(regionX, regionZ);
213+
if(chunkDataOutputStream == null){
214+
System.out.println(chunkX % 32);
215+
System.out.println(chunkZ % 32);
216+
}
217+
NbtIo.write(tag, chunkDataOutputStream);
218+
chunkDataOutputStream.close();
219+
}
220+
}
221+
}
222+
finally{
223+
Iterator<Entry<String, RegionFile>> iter = regions.entrySet().iterator();
224+
while (iter.hasNext()){
225+
Entry<String, RegionFile> entry = iter.next();
226+
RegionFile region = entry.getValue();
227+
region.close();
228+
}
229+
iterator.close();
230+
}
231+
}
232+
finally{
233+
db.close();
234+
}
235+
System.out.println("Done!");
236+
}
237+
238+
public static String byte2s(byte[] b, boolean ignoreTooLong){
239+
String s = "0x";
240+
int length = b.length;
241+
boolean tooLong = false;
242+
if(length > 100){
243+
length = 100;
244+
tooLong = true;
245+
}
246+
for(int i = 0; i < length; i++){
247+
s = s + b[i] + " ";
248+
}
249+
if(tooLong && ignoreTooLong)
250+
s = s + "...";
251+
return s;
252+
}
253+
254+
public static byte[] intToByteArray(int i){
255+
byte[] result = new byte[4];
256+
result[0] = (byte)((i >> 24) & 0xFF);
257+
result[1] = (byte)((i >> 16) & 0xFF);
258+
result[2] = (byte)((i >> 8) & 0xFF);
259+
result[3] = (byte)(i & 0xFF);
260+
return result;
261+
}
262+
263+
public static int byteArrayToInt(byte[] bytes){
264+
int value= 0;
265+
for (int i = 0; i < 4; i++){
266+
int shift = (4 - 1 - i) * 8;
267+
value += (bytes[i] & 0x000000FF) << shift;
268+
}
269+
return value;
270+
}
271+
272+
public static class LevelDBChunk{
273+
public OldDataLayer blockLight;
274+
public OldDataLayer skyLight;
275+
public OldDataLayer data;
276+
public byte[] blocks;
277+
278+
public final int x;
279+
public final int z;
280+
281+
public LevelDBChunk(int x, int z){
282+
this.x = x;
283+
this.z = z;
284+
}
285+
}
286+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package com.mojang.nbt;
2+
3+
/**
4+
* Copyright Mojang AB.
5+
*
6+
* Don't do evil.
7+
*/
8+
9+
import java.io.*;
10+
11+
public class ByteArrayTag extends Tag {
12+
public byte[] data;
13+
14+
public ByteArrayTag(String name) {
15+
super(name);
16+
}
17+
18+
public ByteArrayTag(String name, byte[] data) {
19+
super(name);
20+
this.data = data;
21+
}
22+
23+
void write(DataOutput dos) throws IOException {
24+
dos.writeInt(data.length);
25+
dos.write(data);
26+
}
27+
28+
void load(DataInput dis) throws IOException {
29+
int length = dis.readInt();
30+
data = new byte[length];
31+
dis.readFully(data);
32+
}
33+
34+
public byte getId() {
35+
return TAG_Byte_Array;
36+
}
37+
38+
public String toString() {
39+
return "[" + data.length + " bytes]";
40+
}
41+
42+
@Override
43+
public boolean equals(Object obj) {
44+
if (super.equals(obj)) {
45+
ByteArrayTag o = (ByteArrayTag) obj;
46+
return ((data == null && o.data == null) || (data != null && data.equals(o.data)));
47+
}
48+
return false;
49+
}
50+
51+
@Override
52+
public Tag copy() {
53+
byte[] cp = new byte[data.length];
54+
System.arraycopy(data, 0, cp, 0, data.length);
55+
return new ByteArrayTag(getName(), cp);
56+
}
57+
}

src/com/mojang/nbt/ByteTag.java

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package com.mojang.nbt;
2+
3+
/**
4+
* Copyright Mojang AB.
5+
*
6+
* Don't do evil.
7+
*/
8+
9+
import java.io.*;
10+
11+
public class ByteTag extends Tag {
12+
public byte data;
13+
14+
public ByteTag(String name) {
15+
super(name);
16+
}
17+
18+
public ByteTag(String name, byte data) {
19+
super(name);
20+
this.data = data;
21+
}
22+
23+
void write(DataOutput dos) throws IOException {
24+
dos.writeByte(data);
25+
}
26+
27+
void load(DataInput dis) throws IOException {
28+
data = dis.readByte();
29+
}
30+
31+
public byte getId() {
32+
return TAG_Byte;
33+
}
34+
35+
public String toString() {
36+
return "" + data;
37+
}
38+
39+
@Override
40+
public boolean equals(Object obj) {
41+
if (super.equals(obj)) {
42+
ByteTag o = (ByteTag) obj;
43+
return data == o.data;
44+
}
45+
return false;
46+
}
47+
48+
@Override
49+
public Tag copy() {
50+
return new ByteTag(getName(), data);
51+
}
52+
}

0 commit comments

Comments
 (0)