public void Deserialize(XmlAttribute xml) { var name = xml.Name; if (name[0] == '_') { Hash = int.Parse(name.Substring(1), NumberStyles.HexNumber); } else { // known attribute :) Name = name; } var type = AttributeTypes.GetType(Hash); // try resolving the full name, e.g. 'Class.bProperty' var fullHash = StringHasher.GetHash(FullName); if (fullHash != Hash) { if (AttributeTypes.IsTypeKnown(fullHash)) { type = AttributeTypes.GetType(fullHash); } } Data = new AttributeData(type, xml.Value); // looks to be part of the spec :/ //if (Data.Type != type) // Debug.WriteLine($"Attribute '{FullName}' was created as a '{type.ToString()}' but was actually a '{Data.Type.ToString()}'!"); }
public StringId(string name) { m_Length = name.Length; m_Hash = StringHasher.GetHash(name); m_Name = name; }
public static void RegisterType(string name, DataType type) { var hash = StringHasher.GetHash(name); if (!m_userTypes.ContainsKey(hash)) { m_userTypes.Add(hash, type); } }
public static StringId Parse(int hash) { StringId result = hash; var name = String.Empty; if (StringHasher.TryResolveHash(result, out name)) { result = name; } return(result); }
public string ToStringId() { var value = ToInt32(); var hashStr = StringHasher.ResolveHash(value); if (hashStr != null) { return(String.Concat("$", hashStr)); } return((value != 0) ? ToHexString() : String.Empty); }
public void Deserialize(BinaryStream stream, bool readHash) { if (readHash) { var hash = stream.ReadInt32(); var name = StringHasher.ResolveHash(hash); var type = AttributeTypes.GetType(hash); // cannot be null or contain spaces var nameResolved = ((name != null) && !name.Contains(" ")); if (nameResolved) { Name = name; } else { Hash = hash; } // try resolving the full name, e.g. 'Class.bProperty' var fullHash = StringHasher.GetHash(FullName); if (fullHash != hash) { if (AttributeTypes.IsTypeKnown(fullHash)) { type = AttributeTypes.GetType(fullHash); } } Data = new AttributeData(type); } else { Deserialize(stream); } }
public void Deserialize(NodeClass node) { if (node.Attributes.Count > 0) { foreach (var attr in node.Attributes) { if (attr.Hash == StringHasher.GetHash("Name")) { Name = attr.Data.ToString(); break; } } } var nChildren = node.Children.Count; Entries = new List <EntityReference>(nChildren); // _256A1FF9 nodes foreach (var group in node.Children) { if (group.Children.Count != 1) { throw new InvalidOperationException("Houston, we got a bit of a problem..."); } var entry = new EntityReference() { Use32Bit = Use32Bit, GroupNode = group, EntityNode = group.Children[0], }; Entries.Add(entry); } }
public static byte[] Parse(string s, ref DataType type) { if (s.Length == 0) { // the following MUST have a null terminator! switch (type) { case DataType.String: case DataType.RML: return(new byte[1] { 0 }); } switch (type) { case DataType.StringId: case DataType.PathId: type = DataType.BinHex; return(BitConverter.GetBytes(-1)); } // for others, the resulting buffer can be empty return(new byte[0]); } switch (type) { case DataType.Bool: case DataType.Byte: { var value = byte.Parse(s); return(new byte[1] { value }); } case DataType.Int16: { var value = short.Parse(s); return(BitConverter.GetBytes(value)); } case DataType.UInt16: { var value = ushort.Parse(s); return(BitConverter.GetBytes(value)); } case DataType.Int32: { var value = int.Parse(s); return(BitConverter.GetBytes(value)); } case DataType.UInt32: { var value = uint.Parse(s); return(BitConverter.GetBytes(value)); } case DataType.Float: { var value = float.Parse(s); return(BitConverter.GetBytes(value)); } case DataType.Vector2: case DataType.Vector3: case DataType.Vector4: { var vals = s.Split(','); if (vals.Length < 2) { throw new InvalidOperationException($"Invalid vector value '{s}'"); } var fVals = new float[4]; for (int i = 0; i < vals.Length; i++) { fVals[i] = float.Parse(vals[i]); } var nVals = 0; if (type == DataType.Vector2) { nVals = 2; } if (type == DataType.Vector3) { nVals = 3; } if (type == DataType.Vector4) { nVals = 4; } var buffer = new byte[nVals * 4]; for (int v = 0; v < nVals; v++) { var f = BitConverter.GetBytes(fVals[v]); System.Buffer.BlockCopy(f, 0, buffer, (v * 4), 4); } return(buffer); } case DataType.RML: return(Utils.GetStringBuffer(s)); } switch (s[0]) { // StringId case '$': var str = s.Substring(1); var hash = StringHasher.GetHash(str); StringHasher.AddToLookup(str); type = DataType.StringId; return(BitConverter.GetBytes(hash)); // BinHex case '#': { if (Utils.IsHexString(s)) { type = DataType.BinHex; return(Utils.HexString2Bytes(s)); } } break; // Array case '[': { // strip the braces var aryStr = s.Substring(1, s.Length - 2); var aryVals = aryStr.Split(','); var count = aryVals.Length; var offset = 0; var size = -1; byte[] buffer = null; for (int i = 0; i < count; i++) { var aryVal = aryVals[i]; var value = Utils.HexString2Bytes(aryVal); if (buffer == null) { size = value.Length; buffer = new byte[(count * size) + 4]; var cBuf = BitConverter.GetBytes(count); System.Buffer.BlockCopy(cBuf, 0, buffer, 0, 4); offset = 4; } else { if (value.Length != size) { throw new InvalidDataException("Array element size mismatch!"); } } System.Buffer.BlockCopy(value, 0, buffer, offset, size); offset += size; } return(buffer); } } if (Utils.IsHexString(s)) { return(Utils.HexString2Bytes(s)); } // return as string type = DataType.String; // if it's a StringId, require '$' prefix if (type == DataType.StringId) { throw new InvalidDataException("Malformed StringId -- string must have a prefix!"); } return(Utils.GetStringBuffer(s)); }
public void Deserialize(BinaryStream stream, List <NodeObject> objRefs) { Offset = (int)stream.Position; // define reference type just in case we f**k up somehow var nD = DescriptorTag.Read(stream, ReferenceType.Index); if (nD.Type == DescriptorType.Reference) { throw new InvalidOperationException("Cannot deserialize an object reference directly!"); } var nChildren = nD.Value; Children = new List <NodeObject>(nChildren); var hash = stream.ReadInt32(); var name = StringHasher.ResolveHash(hash); if (name != null) { Name = name; } else { Hash = hash; } // add a reference to this object objRefs.Add(this); var aD = DescriptorTag.Read(stream, ReferenceType.Index); var nAttrs = aD.Value; Attributes = new List <NodeAttribute>(nAttrs); if (nAttrs > 0) { for (int i = 0; i < nAttrs; i++) { // hash and data inline var attr = new NodeAttribute(stream, Name); attr.Deserialize(stream); Attributes.Add(attr); } } if (nChildren > 0) { // read children for (int n = 0; n < nChildren; n++) { var cP = (int)stream.Position; var cD = DescriptorTag.Read(stream, ReferenceType.Index); // rip if (cD.IsIndex) { var idx = cD.Value; var childRef = objRefs[idx]; Children.Add(childRef); } else { // move back stream.Position = cP; var child = new NodeObject(stream, objRefs); Children.Add(child); } } } }
private static bool RegisterTypeToLookup(TypeLookup lookup, string name, int hash, DataType type) { if (name != null) { if (hash != -1) { // add manual lookup StringHasher.AddToLookup(hash, name); } else { hash = StringHasher.GetHash(name); // try adding this to the lookup if (!StringHasher.CanResolveHash(hash)) { Debug.WriteLine($"- Adding '{name}' to lookup"); StringHasher.AddToLookup(name); } } if (!lookup.ContainsKey(hash)) { lookup.Add(hash, type); } var id = name; var parentId = ""; var splitIdx = name.LastIndexOf('.'); if (splitIdx != -1) { parentId = name.Substring(0, splitIdx); id = name.Substring(splitIdx + 1); StringHasher.AddToLookup(parentId); StringHasher.AddToLookup(id); } // auto-register accompanying "text_*" string if ((type == DataType.StringId) || (type == DataType.PathId)) { id = $"text_{id}"; if (!String.IsNullOrEmpty(parentId)) { id = $"{parentId}.{id}"; } RegisterTypeToLookup(lookup, id, -1, DataType.String); } } else { // empty attribute!? if (hash == -1) { return(false); } //--var canResolve = StringHasher.CanResolveHash(hash); //-- //--name = (canResolve) //-- ? StringHasher.ResolveHash(hash) //-- : $"_{hash:X8}"; //-- //--if (canResolve) //--{ //-- if (IsTypeKnown(hash)) //-- { //-- var knownType = GetType(hash); //-- //-- //WriteUniqueHint($"<!-- Remove: --><Attribute Hash=\"{attrHash:X8}\" Type=\"{attrType.ToString()}\" /><!-- SameAs --><Attribute Name=\"{name}\" Type=\"{knownType.ToString()}\" />"); //-- } //-- else //-- { //-- //WriteUniqueHint($"<!-- Rename: --><Attribute Hash=\"{attrHash:X8}\" Type=\"{attrType.ToString()}\" /><!-- EqualTo --><Attribute Name=\"{name}\" Type=\"{attrType.ToString()}\" />"); //-- } //--} if (!lookup.ContainsKey(hash)) { lookup.Add(hash, type); } } return(true); }
public override void Deserialize(BinaryStream stream) { var ptr = (int)stream.Position; var nD = DescriptorTag.Read(stream, ReferenceType.Offset); if (nD.IsOffset) { stream.Position = nD.Value; Deserialize(stream); stream.Position = (ptr + nD.Size); } else { Offset = ptr; var nChildren = nD.Value; Children = new List <NodeClass>(nChildren); var hash = stream.ReadInt32(); var size = stream.ReadInt16(); var name = StringHasher.ResolveHash(hash); if (name != null) { Name = name; } else { Hash = hash; } var attrsPtr = (int)stream.Position; var next = (attrsPtr + size); if (size != 0) { var nhD = DescriptorTag.Read(stream, ReferenceType.Offset); var adjustPtr = false; if (nhD.IsOffset) { stream.Position = nhD.Value; // read again nhD = DescriptorTag.Read(stream, ReferenceType.Offset); if (nhD.IsOffset) { throw new InvalidOperationException("Cannot have nested offsets!"); } // adjust ptr to attributes attrsPtr += nhD.Size; adjustPtr = true; } var nAttrs = nhD.Value; Attributes = new List <NodeAttribute>(nAttrs); for (int i = 0; i < nAttrs; i++) { var attr = new NodeAttribute(stream, Name); Attributes.Add(attr); } // move to the attributes if needed if (adjustPtr) { stream.Position = attrsPtr; } // deserialize attribute data foreach (var attr in Attributes) { attr.Deserialize(stream); } } else { throw new NotImplementedException("Zero-length nodes are not covered under TrumpCare™."); } if (stream.Position != next) { throw new InvalidOperationException("You dun f****d up, son!"); } // read children for (int n = 0; n < nChildren; n++) { var child = new NodeClass(stream); Children.Add(child); } } }