diff options
author | Scott Barta <sbarta@google.com> | 2012-03-01 12:35:35 -0800 |
---|---|---|
committer | Scott Barta <sbarta@google.com> | 2012-03-01 12:40:08 -0800 |
commit | 59b2e6871c65f58fdad78cd7229c292f6a177578 (patch) | |
tree | 2d4e7bfc05b93f40b34675d77e403dd1c25efafd /engine/src/core-plugins/com/jme3/export/binary/BinaryImporter.java | |
parent | f9b30489e75ac1eabc365064959804e99534f7ab (diff) | |
download | jmonkeyengine-59b2e6871c65f58fdad78cd7229c292f6a177578.tar.gz |
Adds the jMonkeyEngine library to the build.
Adds the jMonkeyEngine open source 3D game engine to the build. This
is built as a static library and is only used by the Finsky client.
Change-Id: I06a3f054df7b8a67757267d884854f70c5a16ca0
Diffstat (limited to 'engine/src/core-plugins/com/jme3/export/binary/BinaryImporter.java')
-rw-r--r-- | engine/src/core-plugins/com/jme3/export/binary/BinaryImporter.java | 361 |
1 files changed, 361 insertions, 0 deletions
diff --git a/engine/src/core-plugins/com/jme3/export/binary/BinaryImporter.java b/engine/src/core-plugins/com/jme3/export/binary/BinaryImporter.java new file mode 100644 index 0000000..7f94ba4 --- /dev/null +++ b/engine/src/core-plugins/com/jme3/export/binary/BinaryImporter.java @@ -0,0 +1,361 @@ +/* + * Copyright (c) 2009-2010 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.jme3.export.binary; + +import com.jme3.asset.AssetInfo; +import com.jme3.asset.AssetManager; +import com.jme3.export.*; +import com.jme3.math.FastMath; +import java.io.*; +import java.net.URL; +import java.nio.ByteOrder; +import java.util.HashMap; +import java.util.IdentityHashMap; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * @author Joshua Slack + * @author Kirill Vainer - Version number, Fast buffer reading + */ +public final class BinaryImporter implements JmeImporter { + private static final Logger logger = Logger.getLogger(BinaryImporter.class + .getName()); + + private AssetManager assetManager; + + //Key - alias, object - bco + private HashMap<String, BinaryClassObject> classes + = new HashMap<String, BinaryClassObject>(); + //Key - id, object - the savable + private HashMap<Integer, Savable> contentTable + = new HashMap<Integer, Savable>(); + //Key - savable, object - capsule + private IdentityHashMap<Savable, BinaryInputCapsule> capsuleTable + = new IdentityHashMap<Savable, BinaryInputCapsule>(); + //Key - id, opject - location in the file + private HashMap<Integer, Integer> locationTable + = new HashMap<Integer, Integer>(); + + public static boolean debug = false; + + private byte[] dataArray; + private int aliasWidth; + private int formatVersion; + + private static final boolean fastRead = ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN; + + public BinaryImporter() { + } + + public int getFormatVersion(){ + return formatVersion; + } + + public static boolean canUseFastBuffers(){ + return fastRead; + } + + public static BinaryImporter getInstance() { + return new BinaryImporter(); + } + + public void setAssetManager(AssetManager manager){ + this.assetManager = manager; + } + + public AssetManager getAssetManager(){ + return assetManager; + } + + public Object load(AssetInfo info){ +// if (!(info.getKey() instanceof ModelKey)) +// throw new IllegalArgumentException("Model assets must be loaded using a ModelKey"); + + assetManager = info.getManager(); + + InputStream is = null; + try { + is = info.openStream(); + Savable s = load(is); + + return s; + } catch (IOException ex) { + logger.log(Level.SEVERE, "An error occured while loading jME binary object", ex); + } finally { + if (is != null){ + try { + is.close(); + } catch (IOException ex) {} + } + } + return null; + } + + public Savable load(InputStream is) throws IOException { + return load(is, null, null); + } + + public Savable load(InputStream is, ReadListener listener) throws IOException { + return load(is, listener, null); + } + + public Savable load(InputStream is, ReadListener listener, ByteArrayOutputStream baos) throws IOException { + contentTable.clear(); + BufferedInputStream bis = new BufferedInputStream(is); + + int numClasses; + + // Try to read signature + int maybeSignature = ByteUtils.readInt(bis); + if (maybeSignature == FormatVersion.SIGNATURE){ + // this is a new version J3O file + formatVersion = ByteUtils.readInt(bis); + numClasses = ByteUtils.readInt(bis); + + // check if this binary is from the future + if (formatVersion > FormatVersion.VERSION){ + throw new IOException("The binary file is of newer version than expected! " + + formatVersion + " > " + FormatVersion.VERSION); + } + }else{ + // this is an old version J3O file + // the signature was actually the class count + numClasses = maybeSignature; + + // 0 indicates version before we started adding + // version numbers + formatVersion = 0; + } + + int bytes = 4; + aliasWidth = ((int)FastMath.log(numClasses, 256) + 1); + + classes.clear(); + for(int i = 0; i < numClasses; i++) { + String alias = readString(bis, aliasWidth); + + // jME3 NEW: Read class version number + int[] classHierarchyVersions; + if (formatVersion >= 1){ + int classHierarchySize = bis.read(); + classHierarchyVersions = new int[classHierarchySize]; + for (int j = 0; j < classHierarchySize; j++){ + classHierarchyVersions[j] = ByteUtils.readInt(bis); + } + }else{ + classHierarchyVersions = new int[]{ 0 }; + } + + // read classname and classname size + int classLength = ByteUtils.readInt(bis); + String className = readString(bis, classLength); + + BinaryClassObject bco = new BinaryClassObject(); + bco.alias = alias.getBytes(); + bco.className = className; + bco.classHierarchyVersions = classHierarchyVersions; + + int fields = ByteUtils.readInt(bis); + bytes += (8 + aliasWidth + classLength); + + bco.nameFields = new HashMap<String, BinaryClassField>(fields); + bco.aliasFields = new HashMap<Byte, BinaryClassField>(fields); + for (int x = 0; x < fields; x++) { + byte fieldAlias = (byte)bis.read(); + byte fieldType = (byte)bis.read(); + + int fieldNameLength = ByteUtils.readInt(bis); + String fieldName = readString(bis, fieldNameLength); + BinaryClassField bcf = new BinaryClassField(fieldName, fieldAlias, fieldType); + bco.nameFields.put(fieldName, bcf); + bco.aliasFields.put(fieldAlias, bcf); + bytes += (6 + fieldNameLength); + } + classes.put(alias, bco); + } + if (listener != null) listener.readBytes(bytes); + + int numLocs = ByteUtils.readInt(bis); + bytes = 4; + + capsuleTable.clear(); + locationTable.clear(); + for(int i = 0; i < numLocs; i++) { + int id = ByteUtils.readInt(bis); + int loc = ByteUtils.readInt(bis); + locationTable.put(id, loc); + bytes += 8; + } + + @SuppressWarnings("unused") + int numbIDs = ByteUtils.readInt(bis); // XXX: NOT CURRENTLY USED + int id = ByteUtils.readInt(bis); + bytes += 8; + if (listener != null) listener.readBytes(bytes); + + if (baos == null) { + baos = new ByteArrayOutputStream(bytes); + } else { + baos.reset(); + } + int size = -1; + byte[] cache = new byte[4096]; + while((size = bis.read(cache)) != -1) { + baos.write(cache, 0, size); + if (listener != null) listener.readBytes(size); + } + bis = null; + + dataArray = baos.toByteArray(); + baos = null; + + Savable rVal = readObject(id); + if (debug) { + logger.info("Importer Stats: "); + logger.log(Level.INFO, "Tags: {0}", numClasses); + logger.log(Level.INFO, "Objects: {0}", numLocs); + logger.log(Level.INFO, "Data Size: {0}", dataArray.length); + } + dataArray = null; + return rVal; + } + + public Savable load(URL f) throws IOException { + return load(f, null); + } + + public Savable load(URL f, ReadListener listener) throws IOException { + InputStream is = f.openStream(); + Savable rVal = load(is, listener); + is.close(); + return rVal; + } + + public Savable load(File f) throws IOException { + return load(f, null); + } + + public Savable load(File f, ReadListener listener) throws IOException { + FileInputStream fis = new FileInputStream(f); + Savable rVal = load(fis, listener); + fis.close(); + return rVal; + } + + public Savable load(byte[] data) throws IOException { + ByteArrayInputStream bais = new ByteArrayInputStream(data); + Savable rVal = load(bais); + bais.close(); + return rVal; + } + + @Override + public InputCapsule getCapsule(Savable id) { + return capsuleTable.get(id); + } + + protected String readString(InputStream f, int length) throws IOException { + byte[] data = new byte[length]; + for(int j = 0; j < length; j++) { + data[j] = (byte)f.read(); + } + + return new String(data); + } + + protected String readString(int length, int offset) throws IOException { + byte[] data = new byte[length]; + for(int j = 0; j < length; j++) { + data[j] = dataArray[j+offset]; + } + + return new String(data); + } + + public Savable readObject(int id) { + + if(contentTable.get(id) != null) { + return contentTable.get(id); + } + + try { + int loc = locationTable.get(id); + + String alias = readString(aliasWidth, loc); + loc+=aliasWidth; + + BinaryClassObject bco = classes.get(alias); + + if(bco == null) { + logger.logp(Level.SEVERE, this.getClass().toString(), "readObject(int id)", "NULL class object: " + alias); + return null; + } + + int dataLength = ByteUtils.convertIntFromBytes(dataArray, loc); + loc+=4; + + Savable out = null; + if (assetManager != null) { + out = SavableClassUtil.fromName(bco.className, assetManager.getClassLoaders()); + } else { + out = SavableClassUtil.fromName(bco.className); + } + + BinaryInputCapsule cap = new BinaryInputCapsule(this, out, bco); + cap.setContent(dataArray, loc, loc+dataLength); + + capsuleTable.put(out, cap); + contentTable.put(id, out); + + out.read(this); + + capsuleTable.remove(out); + + return out; + + } catch (IOException e) { + logger.logp(Level.SEVERE, this.getClass().toString(), "readObject(int id)", "Exception", e); + return null; + } catch (ClassNotFoundException e) { + logger.logp(Level.SEVERE, this.getClass().toString(), "readObject(int id)", "Exception", e); + return null; + } catch (InstantiationException e) { + logger.logp(Level.SEVERE, this.getClass().toString(), "readObject(int id)", "Exception", e); + return null; + } catch (IllegalAccessException e) { + logger.logp(Level.SEVERE, this.getClass().toString(), "readObject(int id)", "Exception", e); + return null; + } + } +}
\ No newline at end of file |