99import net .minecraft .world .level .chunk .DataLayer ;
1010import net .minecraft .world .level .chunk .OldDataLayer ;
1111import net .minecraft .world .level .chunk .storage .*;
12+
1213import static org .iq80 .leveldb .impl .Iq80DBFactory .*;
1314
1415import java .io .*;
1718import java .util .Map .Entry ;
1819
1920public 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 ;
21+ private final static int DATALAYER_BITS = 4 ;
22+ private final static int BLOCKDATA_BYTES = 4096 ;
23+ private final static int METADATA_BYTES = 2048 ;
24+ private final static int SKYLIGHTDATA_BYTES = 2048 ;
25+ private final static int BLOCKLIGHTDATA_BYTES = 2048 ;
2526
2627 public static void main (String [] args ) throws IOException {
2728 //System.out.println((-1 % 32 + 32) % 32);
@@ -91,139 +92,191 @@ public static void convert(File src, File des) throws IOException{
9192 DBIterator iterator = db .iterator ();
9293 //ArrayList<byte[]> keys = new ArrayList<byte[]>();
9394 HashMap <String , RegionFile > regions = new HashMap <String , RegionFile >();
95+ HashMap <String , CompoundTag > comChunks = new HashMap <>();
96+ HashMap <String , Integer > chunkHeight = new HashMap <>();
9497 try {
9598 for (iterator .seekToFirst (); iterator .hasNext (); iterator .next ()){
9699 byte [] key = iterator .peekNext ().getKey ();
97- if (key .length == 9 && key [8 ] == 0x30 ){
98- byte [] value = iterator .peekNext ().getValue ();
100+ //System.out.println(byte2s(key, false));
101+ byte [] value = iterator .peekNext ().getValue ();
102+ //System.out.println("Length: " + value.length);
103+ if (key .length == 10 && key [8 ] == 47 ){
104+
105+
99106 int chunkX = byteArrayToInt (new byte []{key [3 ], key [2 ], key [1 ], key [0 ]});
100107 int chunkZ = byteArrayToInt (new byte []{key [7 ], key [6 ], key [5 ], key [4 ]});
101- System .out .println ("Converting chunk X:" +chunkX +" Z:" +chunkZ );
108+ int chunkY = (int ) key [9 ];
109+
110+ System .out .print ("\r Converting subchunk X: " +chunkX +" Z: " +chunkZ +" Y: " +chunkY +" " );
111+ System .out .flush ();
102112 totalChunk ++;
103- CompoundTag tag = new CompoundTag ();
104- CompoundTag levelData = new CompoundTag ();
105- tag .put ("Level" , levelData );
106113
107- levelData .putByte ("LightPopulated" , (byte )1 );
108- levelData .putByte ("TerrainPopulated" , (byte )1 );
109- levelData .putByte ("V" , (byte )1 );
110- levelData .putInt ("xPos" , chunkX );
111- levelData .putInt ("zPos" , chunkZ );
112- levelData .putLong ("InhabitedTime" , 0 );
113- levelData .putLong ("LastUpdate" , 0 );
114- byte [] biomes = new byte [16 * 16 ];
115- for (int i = 0 ; i <256 ; i ++)
116- biomes [i ] = -1 ;
117- levelData .putByteArray ("Biomes" , biomes );
118- levelData .put ("Entities" , new ListTag <CompoundTag >("Entities" ));
114+ String comKey = chunkX +"," +chunkZ ;
115+ if (!comChunks .containsKey (comKey )){
116+ //System.out.println("New comChunks");
117+ CompoundTag tag = new CompoundTag ();
118+ CompoundTag levelData = new CompoundTag ();
119+ tag .put ("Level" , levelData );
120+
121+ levelData .putByte ("LightPopulated" , (byte )1 );
122+ levelData .putByte ("TerrainPopulated" , (byte )1 );
123+ levelData .putByte ("V" , (byte )1 );
124+ levelData .putInt ("xPos" , chunkX );
125+ levelData .putInt ("zPos" , chunkZ );
126+ levelData .putLong ("InhabitedTime" , 0 );
127+ levelData .putLong ("LastUpdate" , 0 );
128+
129+ byte [] biomes = new byte [16 * 16 ];
130+ for (int i = 0 ; i <256 ; i ++)
131+ biomes [i ] = -1 ;
132+ levelData .putByteArray ("Biomes" , biomes );
133+
134+ levelData .put ("Entities" , new ListTag <CompoundTag >("Entities" ));
135+
136+ ListTag <CompoundTag > sectionTags = new ListTag <CompoundTag >("Sections" );
137+ levelData .put ("Sections" , sectionTags );
138+
139+ levelData .put ("TileEntities" , new ListTag <CompoundTag >("TileEntities" ));
140+
141+ comChunks .put (comKey , tag );
142+ }
143+
144+
145+
146+ CompoundTag tag = comChunks .get (comKey );
147+ CompoundTag levelData = tag .getCompound ("Level" );
119148
120- ListTag <CompoundTag > sectionTags = new ListTag <CompoundTag >("Sections" );
149+ @ SuppressWarnings ("unchecked" )
150+ ListTag <CompoundTag > sectionTags = (ListTag <CompoundTag >) levelData .getList ("Sections" );
121151
122152 LevelDBChunk data = new LevelDBChunk (chunkX , chunkZ );
123153
154+ int offset = 1 ;
155+
124156 data .blocks = new byte [BLOCKDATA_BYTES ];
125- System .arraycopy (value , 0 , data .blocks , 0 , BLOCKDATA_BYTES );
157+ System .arraycopy (value , offset , data .blocks , 0 , BLOCKDATA_BYTES );
158+ offset += BLOCKDATA_BYTES ;
126159
127160 byte [] metadata = new byte [METADATA_BYTES ];
128- System .arraycopy (value , BLOCKDATA_BYTES , metadata , 0 , METADATA_BYTES );
161+ System .arraycopy (value , offset , metadata , 0 , METADATA_BYTES );
162+ offset += METADATA_BYTES ;
129163 data .data = new OldDataLayer (metadata , DATALAYER_BITS );
130164
131165 byte [] skyLightData = new byte [SKYLIGHTDATA_BYTES ];
132- System .arraycopy (value , BLOCKDATA_BYTES + METADATA_BYTES , skyLightData , 0 , SKYLIGHTDATA_BYTES );
166+ if (offset + SKYLIGHTDATA_BYTES < value .length )
167+ System .arraycopy (value , offset , skyLightData , 0 , SKYLIGHTDATA_BYTES );
168+ offset += SKYLIGHTDATA_BYTES ;
133169 data .skyLight = new OldDataLayer (skyLightData , DATALAYER_BITS );
134170
135171 byte [] blockLightData = new byte [BLOCKLIGHTDATA_BYTES ];
136- System .arraycopy (value , BLOCKDATA_BYTES + METADATA_BYTES + SKYLIGHTDATA_BYTES , blockLightData , 0 , BLOCKLIGHTDATA_BYTES );
172+ if (offset + BLOCKLIGHTDATA_BYTES < value .length )
173+ System .arraycopy (value , offset , blockLightData , 0 , BLOCKLIGHTDATA_BYTES );
137174 data .blockLight = new OldDataLayer (blockLightData , DATALAYER_BITS );
138175
139- for (int yBase = 0 ; yBase < (128 / 16 ); yBase ++) {
140-
141- // find non-air
142- boolean allAir = true ;
143- for (int x = 0 ; x < 16 && allAir ; x ++) {
144- for (int y = 0 ; y < 16 && allAir ; y ++) {
145- for (int z = 0 ; z < 16 ; z ++) {
146- int pos = (x << 11 ) | (z << 7 ) | (y + (yBase << 4 ));
147- int block = data .blocks [pos ];
148- if (block != 0 ) {
149- allAir = false ;
150- break ;
151- }
152- }
153- }
154- }
176+ byte [] blocks = new byte [16 * 16 * 16 ];
177+ DataLayer dataValues = new DataLayer (blocks .length , 4 );
178+ DataLayer skyLight = new DataLayer (blocks .length , 4 );
179+ DataLayer blockLight = new DataLayer (blocks .length , 4 );
155180
156- if (allAir ) {
157- continue ;
158- }
181+ for (int x = 0 ; x < 16 ; x ++) {
182+ for (int y = 0 ; y < 16 ; y ++) {
183+ for (int z = 0 ; z < 16 ; z ++) {
184+ int pos = (x << 8 ) | (z << 4 ) | y ;
185+ int block = data .blocks [pos ];
159186
160- // build section
161- byte [] blocks = new byte [16 * 16 * 16 ];
162- DataLayer dataValues = new DataLayer (blocks .length , 4 );
163- DataLayer skyLight = new DataLayer (blocks .length , 4 );
164- DataLayer blockLight = new DataLayer (blocks .length , 4 );
187+ blocks [(y << 8 ) | (z << 4 ) | x ] = (byte ) (block & 0xff );
188+ dataValues .set (x , y , z , data .data .get (x , y , z ));
189+ //skyLight.set(x, y, z, data.skyLight.get(x, y, z));
190+ //blockLight.set(x, y, z, data.blockLight.get(x, y, z));
191+ skyLight .set (x , y , z , 0xf );
192+ blockLight .set (x , y , z , 0xf );
193+ }
194+ }
195+ }
165196
166- for (int x = 0 ; x < 16 ; x ++) {
167- for (int y = 0 ; y < 16 ; y ++) {
168- for (int z = 0 ; z < 16 ; z ++) {
169- int pos = (x << 11 ) | (z << 7 ) | (y + (yBase << 4 ));
170- int block = data .blocks [pos ];
197+ CompoundTag sectionTag = new CompoundTag ();
171198
172- blocks [(y << 8 ) | (z << 4 ) | x ] = (byte ) (block & 0xff );
173- dataValues .set (x , y , z , data .data .get (x , y + (yBase << 4 ), z ));
174- skyLight .set (x , y , z , data .skyLight .get (x , y + (yBase << 4 ), z ));
175- blockLight .set (x , y , z , data .blockLight .get (x , y + (yBase << 4 ), z ));
176- }
177- }
178- }
199+ sectionTag .putByte ("Y" , (byte ) (chunkY & 0xff ));
200+ sectionTag .putByteArray ("Blocks" , blocks );
201+ sectionTag .putByteArray ("Data" , dataValues .data );
202+ sectionTag .putByteArray ("SkyLight" , skyLight .data );
203+ sectionTag .putByteArray ("BlockLight" , blockLight .data );
179204
180- CompoundTag sectionTag = new CompoundTag ();
181-
182- sectionTag .putByte ("Y" , (byte ) (yBase & 0xff ));
183- sectionTag .putByteArray ("Blocks" , blocks );
184- sectionTag .putByteArray ("Data" , dataValues .data );
185- sectionTag .putByteArray ("SkyLight" , skyLight .data );
186- sectionTag .putByteArray ("BlockLight" , blockLight .data );
187-
188- sectionTags .add (sectionTag );
189- }
190- levelData .put ("Sections" , sectionTags );
205+ sectionTags .add (sectionTag );
191206
192- levelData .put ("TileEntities" , new ListTag <CompoundTag >("TileEntities" ));
193- int [] heightMap = new int [256 ];
194- for (int x = 0 ; x < 16 ; x ++){
195- for (int z = 0 ; z < 16 ; z ++){
196- for (int y = 127 ; y >= 0 ; y --){
197- int pos = (x << 11 ) | (z << 7 ) | y ;
198- int block = data .blocks [pos ];
199- if (block != 0 ){
200- heightMap [(x << 4 ) | z ] = y ;
201- break ;
202- }
203- }
204- }
205- }
206- levelData .putIntArray ("HeightMap" , heightMap );
207-
208- String k = (chunkX >> 5 ) + "." + (chunkZ >> 5 );
209- if (!regions .containsKey (k )){
210- regions .put (k , new RegionFile (new File (des , "r." + (chunkX >> 5 ) + "." + (chunkZ >> 5 ) + ".mca" )));
211- }
212- RegionFile regionDest = regions .get (k );
213- int regionX = (chunkX % 32 + 32 ) % 32 ;
214- int regionZ = (chunkZ % 32 + 32 ) % 32 ;
215- /*if(chunkX < 0 || chunkZ < 0){
216- @SuppressWarnings("unused")
217- int i = 1+1;
218- }*/
219- DataOutputStream chunkDataOutputStream = regionDest .getChunkDataOutputStream (regionX , regionZ );
220- if (chunkDataOutputStream == null ){
221- System .out .println (chunkX % 32 );
222- System .out .println (chunkZ % 32 );
207+ if (!chunkHeight .containsKey (comKey )) {
208+ chunkHeight .put (comKey , chunkY );
209+ }
210+ else {
211+ int temp = chunkHeight .get (comKey );
212+ if (chunkY > temp )
213+ chunkHeight .put (comKey , chunkY );
214+ }
215+ }
216+ }
217+
218+
219+
220+ Iterator <Entry <String , CompoundTag >> iter = comChunks .entrySet ().iterator ();
221+ while (iter .hasNext ()){
222+ Entry <String , CompoundTag > entry = iter .next ();
223+ String key = entry .getKey ();
224+
225+ CompoundTag tag = entry .getValue ();
226+ CompoundTag levelData = tag .getCompound ("Level" );
227+ @ SuppressWarnings ("unchecked" )
228+ ListTag <CompoundTag > sectionTags = (ListTag <CompoundTag >) levelData .getList ("Sections" );
229+ int topChunk = chunkHeight .get (key );
230+
231+ for (int i = 0 ; i < sectionTags .size (); i ++) {
232+ CompoundTag subChunk = sectionTags .get (i );
233+ int Y = subChunk .getByte ("Y" );
234+ if (Y == topChunk ) {
235+ DataLayer dataValues = new DataLayer (subChunk .getByteArray ("Data" ), 4 );
236+
237+ int [] heightMap = new int [256 ];
238+ for (int x = 0 ; x < 16 ; x ++){
239+ for (int z = 0 ; z < 16 ; z ++){
240+ for (int y = 15 ; y >= 0 ; y --){
241+ int block = dataValues .get (x , y , z );
242+ if (block != 0 ){
243+ heightMap [(x << 4 ) | z ] = (Y << 4 ) | y ;
244+ break ;
245+ }
246+ }
247+ }
248+ }
249+ levelData .putIntArray ("HeightMap" , heightMap );
250+ break ;
223251 }
224- NbtIo .write (tag , chunkDataOutputStream );
225- chunkDataOutputStream .close ();
226252 }
253+ /*
254+ int[] heightMap = new int[256];
255+ for(int x = 0; x < 16; x++){
256+ for(int z = 0; z < 16; z++){
257+ heightMap[(x << 4) | z] = 0;
258+ }
259+ }
260+ levelData.putIntArray("HeightMap", heightMap);
261+ */
262+ String [] parts = key .split ("," );
263+ int chunkX = Integer .parseInt (parts [0 ]);
264+ int chunkZ = Integer .parseInt (parts [1 ]);
265+
266+ String k = (chunkX >> 5 ) + "." + (chunkZ >> 5 );
267+ if (!regions .containsKey (k )){
268+ regions .put (k , new RegionFile (new File (des , "r." + (chunkX >> 5 ) + "." + (chunkZ >> 5 ) + ".mca" )));
269+ }
270+ RegionFile regionDest = regions .get (k );
271+ int regionX = (chunkX % 32 + 32 ) % 32 ;
272+ int regionZ = (chunkZ % 32 + 32 ) % 32 ;
273+ DataOutputStream chunkDataOutputStream = regionDest .getChunkDataOutputStream (regionX , regionZ );
274+ if (chunkDataOutputStream == null ){
275+ System .out .println (chunkX % 32 );
276+ System .out .println (chunkZ % 32 );
277+ }
278+ NbtIo .write (tag , chunkDataOutputStream );
279+ chunkDataOutputStream .close ();
227280 }
228281 }
229282 finally {
@@ -240,7 +293,7 @@ public static void convert(File src, File des) throws IOException{
240293 db .close ();
241294 }
242295 if (totalChunk > 0 ){
243- System .out .println ("Done!" );
296+ System .out .println ("\n Done! totalSubChunks: " + totalChunk );
244297 }
245298 else {
246299 System .out .println ("Oops! It seems that the input data does not contain any valid chunk." );
@@ -275,7 +328,9 @@ public static byte[] intToByteArray(int i){
275328 public static int byteArrayToInt (byte [] bytes ){
276329 int value = 0 ;
277330 for (int i = 0 ; i < 4 ; i ++){
278- int shift = (4 - 1 - i ) * 8 ;
331+ if (bytes .length - i < 1 )
332+ break ;
333+ int shift = (3 - i ) * 8 ;
279334 value += (bytes [i ] & 0x000000FF ) << shift ;
280335 }
281336 return value ;
0 commit comments