public void load(Stream fs) { try { DataReader inr = new DataReader(fs, Encoding.ASCII); // read header int dbVersion = inr.readInt(); if (dbVersion != FILE_FORMAT) { throw new Exception("Wrong database version"); } // create node reader VersionInfo versionInfo = new VersionInfo(); versionInfo.assetVersion = NODE_FORMAT; TypeNodeReader nodeReader = new TypeNodeReader(versionInfo); // read field node table int fieldNodeSize = inr.readInt(); List <TypeNode> typeNodes = new List <TypeNode>(fieldNodeSize); for (int i = 0; i < fieldNodeSize; i++) { TypeNode node = new TypeNode(versionInfo); nodeReader.read(inr, node); typeNodes.Add(node); } // read version string table int versionSize = inr.readInt(); List <UnityVersion> versionsTmp = new List <UnityVersion>(versionSize); for (int i = 0; i < versionSize; i++) { versionsTmp.Add(new UnityVersion(inr.readStringNull())); } // read mapping data int numEntries = inr.readInt(); for (int i = 0; i < numEntries; i++) { int nodeIndex = inr.readInt(); int classID = inr.readInt(); int versionIndex = inr.readInt(); UnityVersion unityVersion = versionsTmp[versionIndex]; UnityClass unityClass = new UnityClass(classID); TypeNode typeNode = typeNodes[nodeIndex]; addEntry(unityClass, unityVersion, typeNode); } } catch (IOException ex) { Logger.Log("Can't read type database" + ex); } }
public void save(Stream os) { // write database file try { DataWriter outw = new DataWriter(os, Encoding.ASCII); // write header outw.writeInt(FILE_FORMAT); // create node writer VersionInfo versionInfo = new VersionInfo(); versionInfo.assetVersion = NODE_FORMAT; TypeNodeWriter nodeWriter = new TypeNodeWriter(versionInfo); // write field node table List <TypeNode> nodesTmp = new List <TypeNode>(new HashSet <TypeNode>(getNodeSet())); outw.writeInt(nodesTmp.Count); foreach (TypeNode typeNode in nodesTmp) { nodeWriter.write(outw, typeNode); } // write version string table List <UnityVersion> versionsTmp = new List <UnityVersion>(new HashSet <UnityVersion>(getVersionSet())); outw.writeInt(versionsTmp.Count); foreach (UnityVersion version in versionsTmp) { outw.writeStringNull(version.ToString()); } // write mapping data outw.writeInt(entries.Count); foreach (TypeTreeDatabaseEntry entry in entries) { UnityClass unityClass = entry.unityClass; UnityVersion unityVersion = entry.unityVersion; TypeNode node = entry.typeNode; int nodeIndex = nodesTmp.IndexOf(node); int classID = unityClass.ID(); int versionIndex = versionsTmp.IndexOf(unityVersion); outw.writeInt(nodeIndex); outw.writeInt(classID); outw.writeInt(versionIndex); } } catch (IOException ex) { Logger.Log("Can't write type database" + ex); } }
public TypeNode getTypeNode(UnityClass unityClass, UnityVersion unityVersion, bool exact) { TypeTreeDatabaseEntry entry = getEntry(unityClass, unityVersion, exact); if (entry != null) { return(entry.typeNode); } else { return(null); } }
public static void embedTypes(AssetFileEx asset) { UnityVersion unityRevision = asset.versionInfo.unityRevision; if (unityRevision == null) { Logger.Log("unityRevision = null"); return; } Dictionary <long, ObjectData> objects = asset.objects; Dictionary <int, EmbeddedTypeInfo> typemap = asset.embeddedTypeMap; foreach (KeyValuePair <long, ObjectData> pair in objects) { ObjectData obj = pair.Value; int typeID = obj.typeID; // skip types that already exist if (typemap.ContainsKey(typeID)) { continue; } TypeNode typeNode = getTypeNode(obj, false); // remove objects with no type tree, which would crash the editor // when loading the file otherwise if (typeNode == null) { Logger.Log("Removing object {0} with unresolvable type {1}" + new Object[] { obj, typeID }); //objectIter.remove(); continue; } typemap[typeID].typeTree = typeNode; } }
//throws IOException private void readheader(DataReader inr) { signature = inr.readStringNull(); streamVersion = inr.readInt(); string s1 = inr.readStringNull(); unityVersion = new UnityVersion(s1); string s2 = inr.readStringNull(); unityRevision = new UnityVersion(s2); minimumStreamedBytes = inr.readUnsignedInt(); headerSize = inr.readInt(); numberOfLevelsToDownload = inr.readInt(); int numberOfLevels = inr.readInt(); //Assert(numberOfLevelsToDownload == numberOfLevels || numberOfLevelsToDownload == 1); for (int i = 0; i < numberOfLevels; i++) { uint PackSize = inr.readUnsignedInt(); uint UncompressedSize = inr.readUnsignedInt(); levelByteEnd[PackSize] = UncompressedSize; } if (streamVersion >= 2) { completeFileSize = inr.readUnsignedInt(); //Assert(minimumStreamedBytes <= completeFileSize); } if (streamVersion >= 3) { dataHeaderSize = inr.readUnsignedInt(); } inr.readByte(); }
public void addEntry(UnityClass unityClass, UnityVersion unityVersion, TypeNode node) { addEntry(new TypeTreeDatabaseEntry(unityClass, unityVersion, node)); }
public TypeTreeDatabaseEntry getEntry(UnityClass unityClass, UnityVersion unityVersion, bool exact) { // search for exact matches string pair = unityClass.name() + "_" + unityVersion.build; TypeTreeDatabaseEntry entryA = null; if (entryMap.ContainsKey(pair)) { entryA = entryMap[pair]; } if (entryA != null) { return(entryA); } // cancel if exact matches are required if (exact) { return(null); } TypeTreeDatabaseEntry entryB = null; UnityVersion versionB = null; TypeTreeDatabaseEntry entryC = null; UnityVersion versionC = null; foreach (TypeTreeDatabaseEntry entry in entries) { UnityClass uclass = entry.unityClass; UnityVersion version = entry.unityVersion; if (uclass.equals(unityClass)) { if (version.major == unityVersion.major) { if (version.minor == unityVersion.minor) { // if major and minor versions match, it will probably work return(entry); } else { // suboptimal choice entryB = entry; versionB = version; } } // worst choice entryC = entry; versionC = version; } } // return less perfect match if (entryB != null) { //Logger.Log( "Unprecise match for class {0} (required: {1}, available: {2})"+ new Object[]{unityClass, unityVersion, versionB}); return(entryB); } // return field node from any revision as the very last resort if (entryC != null) { //Logger.Log("Bad match for class {0} (required: {1}, available: {2})"+ new Object[]{unityClass, unityVersion, versionC}); return(entryC); } // no matches at all return(null); }
public TypeTreeDatabaseEntry(UnityClass unityClass, UnityVersion unityVersion, TypeNode typeNode) { this.unityClass = unityClass; this.unityVersion = unityVersion; this.typeNode = typeNode; }
public static int learnTypes(AssetFileEx asset) { if (asset.isStandalone()) { Logger.Log("File doesn't contain type information"); return(0); } Dictionary <int, EmbeddedTypeInfo> typemap = asset.embeddedTypeMap; UnityVersion unityRevision = asset.versionInfo.unityRevision; if (unityRevision == null) { Logger.Log("unityRevision = null"); return(0); } int learned = 0; // merge the TypeTree map with the database field map foreach (KeyValuePair <int, EmbeddedTypeInfo> typeTreeEntry in typemap) { int typeID = typeTreeEntry.Key; TypeNode typeNode = typeTreeEntry.Value.typeTree; // skip MonoBehaviour types if (typeID < 1) { continue; } UnityClass unityClass = new UnityClass(typeID); TypeNode typeNodeDB = TypeTreeUtils.getTypeNode(unityClass, unityRevision, true); if (typeNodeDB == null) { Logger.Log("New: {0}" + unityClass); TypeTreeDatabase.Instance.addEntry(unityClass, unityRevision, typeNode); typeNodeDB = typeNode; learned++; } // check the hashes, they must be identical at this point //int hash1 = typeNode.hashCode(); //int hash2 = typeNodeDB.hashCode(); //if (hash1 != hash2) //{ // Logger.Log("Database hash mismatch for {0}: {1} != {2}"+ // new Object[] {typeNodeDB.type.typeName(), hash1, hash2}); //} // check if the class name is known and suggest the type base name if not if (unityClass.name() == null) { Logger.Log("Unknown ClassID {0}, suggested name: {1}" + new Object[] { unityClass.ID(), typeNode.type }); } } return(learned); }
public static TypeNode getTypeNode(UnityClass unityClass, UnityVersion unityVersion, bool exact) { return(TypeTreeDatabase.Instance.getTypeNode(unityClass, unityVersion, exact)); }