/* ** 2015 December 01 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. */ package info.ata4.disunity.cli.command.asset; import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameters; import info.ata4.io.buffer.ByteBufferUtils; import info.ata4.io.util.PathUtils; import info.ata4.junity.serialize.SerializedFile; import info.ata4.junity.serialize.SerializedObjectData; import info.ata4.log.LogUtils; import info.ata4.util.io.DataBlock; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.file.Files; import java.nio.file.Path; import static java.nio.file.StandardOpenOption.*; import java.util.logging.Level; import java.util.logging.Logger; /** * * @author Nico Bergemann <barracuda415 at yahoo.de> */ @Parameters( commandDescription = "Split asset file into data blocks." ) public class AssetUnpack extends AssetCommand { private static final Logger L = LogUtils.getLogger(); @Parameter( names = {"-l", "--level"}, description = "Unpacking level" ) private int level = 1; @Override protected void runSerializedFile(Path file, SerializedFile asset) { try { Path outputDir = PathUtils.removeExtension(file); if (Files.isRegularFile(outputDir)) { outputDir = PathUtils.append(outputDir, "_"); } if (Files.notExists(outputDir)) { Files.createDirectory(outputDir); } try (FileChannel fc = FileChannel.open(file)) { DataBlock headerBlock = asset.headerBlock(); Path headerFile = outputDir.resolve("header.block"); copyBlock(headerBlock, headerFile, fc); if (level > 0) { DataBlock typeTreeBlock = asset.metadata().typeTreeBlock(); Path typeTreeFile = outputDir.resolve("type_tree.block"); copyBlock(typeTreeBlock, typeTreeFile, fc); DataBlock objectInfoBlock = asset.metadata().objectInfoBlock(); Path objectInfoFile = outputDir.resolve("object_info.block"); copyBlock(objectInfoBlock, objectInfoFile, fc); DataBlock objectIDBlock = asset.metadata().objectIDBlock(); if (objectIDBlock.length() > 0) { Path objectIDFile = outputDir.resolve("object_ids.block"); copyBlock(objectIDBlock, objectIDFile, fc); } DataBlock fileIdentBlock = asset.metadata().externalsBlock(); Path fileIdentFile = outputDir.resolve("linked_files.block"); copyBlock(fileIdentBlock, fileIdentFile, fc); } else { DataBlock metadataBlock = asset.metadataBlock(); Path metadataFile = outputDir.resolve("metadata.block"); copyBlock(metadataBlock, metadataFile, fc); } if (level < 2) { DataBlock objectDataBlock = asset.objectDataBlock(); Path objectDataFile = outputDir.resolve("object_data.block"); copyBlock(objectDataBlock, objectDataFile, fc); } } if (level > 1) { Path objectDataDir = outputDir.resolve("object_data"); if (Files.notExists(objectDataDir)) { Files.createDirectory(objectDataDir); } for (SerializedObjectData od : asset.objectData()) { String objectDataName = String.format("%010d", od.id()); Path objectDataFile = objectDataDir.resolve(objectDataName + ".block"); ByteBuffer objectDataBuffer = od.buffer(); objectDataBuffer.rewind(); ByteBufferUtils.save(objectDataFile, objectDataBuffer); } } } catch (IOException ex) { L.log(Level.WARNING, "Can't unpack asset file " + file, ex); } } private void copyBlock(DataBlock block, Path file, FileChannel fc) throws IOException { try (FileChannel fcOut = FileChannel.open(file, CREATE, WRITE)) { fc.transferTo(block.offset(), block.length(), fcOut); } } }