/**
* Copyright 2014
* SMEdit https://github.com/StarMade/SMEdit
* SMTools https://github.com/StarMade/SMTools
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
**/
package jo.sm.plugins.ship.imp;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import jo.sm.data.SparseMatrix;
import jo.sm.data.StarMade;
import jo.sm.logic.utils.IntegerUtils;
import jo.sm.logic.utils.ResourceUtils;
import jo.sm.logic.utils.XMLUtils;
import jo.sm.mods.IBlocksPlugin;
import jo.sm.mods.IPluginCallback;
import jo.sm.plugins.ship.imp.nbt.FormatException;
import jo.sm.plugins.ship.imp.nbt.IO;
import jo.sm.plugins.ship.imp.nbt.Tag;
import jo.sm.ship.data.Block;
import jo.sm.ship.logic.ShipLogic;
import jo.sm.ui.BlockTypeColors;
import jo.util.Paths;
import jo.vecmath.Point3i;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
public class ImportSchematicPlugin implements IBlocksPlugin {
public static final String NAME = "Import/Schematic";
public static final String DESC = "Import Schematic file";
public static final String AUTH = "Jo Jaquinta";
public static final int[][] CLASSIFICATIONS
= {
{TYPE_SHIP, SUBTYPE_FILE, 25},
{TYPE_STATION, SUBTYPE_FILE, 25},
{TYPE_SHOP, SUBTYPE_FILE, 25},
{TYPE_PLANET, SUBTYPE_FILE, 25},
{TYPE_FLOATINGROCK, SUBTYPE_FILE, 25},};
private static final Map<Integer, MCMap> BLOCK_MAP = new HashMap<>();
private static long mLastRead = 0;
private static final Logger log = Logger.getLogger(ImportSchematicPlugin.class.getName());
@Override
public String getName() {
return NAME;
}
@Override
public String getDescription() {
return DESC;
}
@Override
public String getAuthor() {
return AUTH;
}
@Override
public Object newParameterBean() {
return new ImportSchematicParameters();
}
@Override
public void initParameterBean(SparseMatrix<Block> original, Object params,
StarMade sm, IPluginCallback cb) {
}
@Override
public int[][] getClassifications() {
return CLASSIFICATIONS;
}
@Override
public SparseMatrix<Block> modify(SparseMatrix<Block> original,
Object p, StarMade sm, IPluginCallback cb) {
readData(sm);
ImportSchematicParameters params;
params = (ImportSchematicParameters) p;
try {
Point3i center;
center = new Point3i(8, 8, 8);
if ((sm.getSelectedLower() != null) && (sm.getSelectedUpper() != null)) {
center.set(sm.getSelectedLower());
center.add(sm.getSelectedUpper());
center.scale(1, 2);
}
SparseMatrix<Block> modified;
modified = new SparseMatrix<>();
readFile(params.getFile(), modified, center, cb);
ShipLogic.ensureCore(modified);
return modified;
} catch (Exception e) {
cb.setError(e);
return null;
}
}
private void readFile(String objFile, SparseMatrix<Block> grid, Point3i center, IPluginCallback cb) throws Exception {
Tag.Compound schematic;
try {
try (DataInputStream rdr = new DataInputStream(new FileInputStream(new File(objFile)))) {
schematic = IO.Read(rdr);
}
} catch (IOException | FormatException e) {
try (DataInputStream rdr = new DataInputStream(new FileInputStream(new File(objFile)))) {
schematic = IO.ReadUncompressed(rdr);
}
}
Tag.Short width = (Tag.Short) schematic.Get("Width");
Tag.Short height = (Tag.Short) schematic.Get("Height");
Tag.Short length = (Tag.Short) schematic.Get("Length");
int xSize;
xSize = width.v;
int ySize;
ySize = height.v;
int zSize;
zSize = length.v;
center.x -= xSize / 2;
center.y -= ySize / 2;
center.z -= zSize / 2;
cb.setStatus("Importing...");
cb.startTask(xSize * ySize * zSize);
Tag.ByteArray blocks = (Tag.ByteArray) schematic.Get("Blocks");
Tag.ByteArray data = (Tag.ByteArray) schematic.Get("Data");
int idx;
idx = 0;
for (int y = 0; y < ySize; y++) {
for (int z = 0; z < zSize; z++) {
for (int x = 0; x < xSize; x++) {
cb.workTask(1);
int blockID;
blockID = blocks.v[idx];
int dataID;
dataID = data.v[idx];
idx++;
MCMap map = BLOCK_MAP.get((dataID << 8) | blockID);
if (map == null) {
map = BLOCK_MAP.get(blockID);
}
if (map == null) {
continue;
}
if (map.mSMBlock > 0) {
grid.set(center.x + x, center.y + y, center.z + z, new Block((short) map.mSMBlock));
}
}
}
}
cb.endTask();
}
private void readData(StarMade sm) {
File plugins = new File(Paths.getPluginsDirectory());
File minecraftTypes;
minecraftTypes = new File(plugins, "schematic_map.xml");
if (minecraftTypes.exists()) {
if (minecraftTypes.lastModified() <= mLastRead) {
return;
}
try {
readDataFile(new FileInputStream(minecraftTypes));
mLastRead = minecraftTypes.lastModified();
return;
} catch (FileNotFoundException e) {
log.log(Level.WARNING, "read Data File failed!", e);
}
}
if (BLOCK_MAP.isEmpty()) {
readDataFile(ResourceUtils.loadSystemResourceStream("schematic_map.xml", ImportSchematicPlugin.class));
}
}
private void readDataFile(InputStream is) {
Document doc = XMLUtils.readStream(is);
if (doc == null) {
return;
}
BLOCK_MAP.clear();
for (Node b : XMLUtils.findNodes(doc, "blockMap/block")) {
MCMap map;
map = new MCMap();
String mcBlock = XMLUtils.getAttribute(b, "mcBlock");
if (MinecraftTypes.NAME_TO_ID.containsKey(mcBlock)) {
map.mMCBlock = MinecraftTypes.NAME_TO_ID.get(mcBlock);
} else {
int mcBlockNum;
mcBlockNum = IntegerUtils.parseInt(mcBlock);
if (mcBlockNum != 0) {
map.mMCBlock = IntegerUtils.parseInt(mcBlock);
} else {
log.log(Level.WARNING, "Unknown MC Block type: " + mcBlock);
continue;
}
}
map.mMCData = IntegerUtils.parseInt(XMLUtils.getAttribute(b, "mcData"));
String smBlock;
smBlock = XMLUtils.getAttribute(b, "smBlock");
if (BlockTypeColors.mBlockTypes.containsKey(smBlock)) {
map.mSMBlock = IntegerUtils.parseInt(BlockTypeColors.mBlockTypes.getProperty(smBlock));
} else {
map.mSMBlock = IntegerUtils.parseInt(smBlock);
}
int idx = map.mMCBlock;
if (map.mMCData != 0) {
idx |= map.mMCData << 8;
}
BLOCK_MAP.put(idx, map);
}
}
class MCMap {
public int mMCBlock;
public int mMCData;
public int mSMBlock;
}
}