/// <summary> /// The instantiation step of the RedEngine-4 reflection. /// </summary> /// <param name="typename">Can be either a generic type such as CUint32 - then converted with GetWKitTypeFromREDType, or a complex type like a /// pointer to a class, a handle to an import file, an array, a soft reference, a static reference, various buffers, an enum.</param> /// <param name="varname">The variable name</param> /// <param name="cr2w">The cr2w base file</param> /// <param name="parentVariable">The class owning this attribute</param> /// <param name="readUnknownAsBytes"></param> /// <returns></returns> public static CVariable Create(string typename, string varname, CR2WFile cr2w, CVariable parentVariable, bool readUnknownAsBytes = true) { typename = REDReflection.GetWKitBaseTypeFromREDBaseType(typename); var fullname = typename; // check for normal type if (AssemblyDictionary.TypeExists(typename)) { var type = AssemblyDictionary.GetTypeByName(typename); if (type != null) { object instance = System.Activator.CreateInstance(type, cr2w, parentVariable, varname); return(instance as CVariable); } } // check for enum types if (AssemblyDictionary.EnumExists(typename)) { Enum e = (Enum)System.Activator.CreateInstance(AssemblyDictionary.GetEnumByName(typename)); var cenum = MakeGenericEnumType(typeof(CEnum <>), e); return(cenum); } else if (CR2WManager.EnumExists(typename)) { Enum e = (Enum)System.Activator.CreateInstance(CR2WManager.GetEnumByName(typename)); var cenum = MakeGenericEnumType(typeof(CEnum <>), e); return(cenum); } // check for generic type else if (typename.StartsWith('[')) { var idx = typename.IndexOf(']'); string generictype = typename[(idx + 1)..];
/// <summary> /// Gets all available types, custom and vanilla for a given typename /// </summary> /// <param name="typename"></param> /// <returns></returns> public static IEnumerable <Type> GetAvailableTypes(string typename) { var availableTypes = new List <Type>(); if (AssemblyDictionary.TypeExists(typename)) { availableTypes.Add(AssemblyDictionary.GetTypeByName(typename)); var subclasses = AssemblyDictionary.GetSubClassesOf(AssemblyDictionary.GetTypeByName(typename)); availableTypes.AddRange(subclasses); // check if subclasses exist in custom assemblies var ssubclasses = CR2WManager.GetSubClassesOf(AssemblyDictionary.GetTypeByName(typename)); availableTypes.AddRange(ssubclasses); } else if (CR2WManager.TypeExists(typename)) { availableTypes.Add(CR2WManager.GetTypeByName(typename)); var subclasses = CR2WManager.GetSubClassesOf(CR2WManager.GetTypeByName(typename)); availableTypes.AddRange(subclasses); // check if subclasses exist in main assembly var ssubclasses = AssemblyDictionary.GetSubClassesOf(CR2WManager.GetTypeByName(typename)); availableTypes.AddRange(ssubclasses); } else { //MainController.LogString( // "No such type exists. Make sure you have all custom types in a .ws file inside the modproject.", // Logtype.Error); return(null); } return(availableTypes.Distinct()); }
public IEnumerable <ICR2WExport> GetReferenceChunks() { var refType = AssemblyDictionary.GetTypeByName(ReferenceType); var types = AssemblyDictionary.GetSubClassesOf(refType) .Select(_ => _.Name).ToList(); return(Cr2wFile.Chunks.Where(cr2WExport => types.Contains(cr2WExport.REDType)).ToList()); }
public void QueueObjects() { var objects = new ObjectInfo[m_exports.Length]; for (int i = 0; i < m_exports.Length; i++) { var e = m_exports[i]; var className = GetCName(e.className); var type = AssemblyDictionary.GetTypeByName(className); if (type == null) { throw new Exception($"Unknown Type: '{className}'"); } BaseStream.Seek(e.dataOffset, SeekOrigin.Begin); var objData = ReadBytes((int)e.dataSize); if (!IgnoreErrors && Crc32Algorithm.Compute(objData) != e.crc32) { throw new MismatchCRC32Exception(); } var instance = Activator.CreateInstance(type); if (instance is CObject obj) { obj.Template = e.template; obj.Flags = (ECObjectFlags)e.objectFlags; } objects[i] = new ObjectInfo() { Instance = instance, NameID = e.className, Data = objData, }; } }
void ParseVariale(string type, int size, string offset) { var arr = type.Split(new char[] { ':' }, 2); switch (arr[0]) { #region .NET Types case "Uint8": { Writer.WriteLine(" {0}", ReadByte()); } return; case "Uint16": { Writer.WriteLine(" {0}", ReadUInt16()); } return; case "Uint32": { Writer.WriteLine(" {0}", ReadUInt32()); } return; case "Uint64": { Writer.WriteLine(" {0}", ReadUInt64()); } return; case "Int8": { Writer.WriteLine(" {0}", ReadSByte()); } return; case "Int16": { Writer.WriteLine(" {0}", ReadInt16()); } return; case "Int32": { Writer.WriteLine(" {0}", ReadInt32()); } return; case "Int64": { Writer.WriteLine(" {0}", ReadInt64()); } return; case "Float": { Writer.WriteLine(" {0}", ReadSingle()); } return; case "String": { var(flag, length) = ReadVLQInt32(); var encoding = flag ? Encoding.ASCII : Encoding.Unicode; var chars = new char[length]; var byteSize = encoding.GetByteCount(chars); var bytes = ReadBytes(byteSize); encoding.GetChars(bytes, 0, byteSize, chars, 0); Writer.WriteLine(" {0}", new string(chars)); } return; case "Bool": { Writer.WriteLine(" {0}", ReadBoolean()); } return; #endregion #region RED Types case "StringAnsi": { var length = ReadByte(); var bytes = ReadBytes(length); Writer.WriteLine(" {0}", new StringAnsi(bytes)); } return; case "CName": { Writer.WriteLine(" {0}", names[ReadUInt16()].Value); } return; case "CGUID": { Writer.WriteLine(" {0}", new CGUID(ReadBytes(16)).ToString()); } return; case "LocalizedString": { Writer.WriteLine(" {0}", ReadUInt32()); } return; case "ptr": { Writer.WriteLine(" Object {0}", ReadUInt32()); } return; case "soft": { var id = ReadUInt16(); if (id == 0) { Writer.WriteLine(" NULL"); return; } var res = resources[id - 1]; Writer.WriteLine(" {0} {1} ({2})", res.Type, res.Path, res.Flags); } return; case "array": { arr = arr[1].Split(new char[] { ',' }, 3); var len = ReadUInt32(); Writer.WriteLine(" {0}", len); Writer.WriteLine("{0}{{", offset.Substring(1)); for (uint i = 0; i < len; i++) { Writer.Write("{0}Id {1}:", offset, i); ParseVariale(arr[2], size, $"\t{offset}"); } Writer.WriteLine("{0}}}", offset.Substring(1)); } return; case "handle": { var id = ReadInt32(); if (id >= 0) { Writer.WriteLine(" Object: {0}", id); } else { id *= -1; var res = resources[id - 1]; Writer.WriteLine(" {0} {1} ({2})", res.Type, res.Path, res.Flags); } } return; case "SAppearanceAttachment": { Writer.WriteLine(); Writer.WriteLine("{0}{{", offset.Substring(1)); ReadVariable(offset); var bytecount = ReadInt32(); var unknown = ReadBytes(bytecount - 4); Writer.WriteLine("{0}Unknown Bytes: {1}", offset, bytecount - 4); Writer.WriteLine("{0}}}", offset.Substring(1)); } return; case "IdTag": { var dynamic = ReadBoolean(); var guid = new CGUID(ReadBytes(16)); if (dynamic) { Writer.WriteLine(" [Dynamic: {0}]", guid.ToString()); } else { Writer.WriteLine(" [Static: {0}]", guid.ToString()); } } return; case "EngineTransform": { Writer.Write(" [ "); var flags = ReadByte(); if ((flags & 1) == 1) { Writer.Write("Posistion:{0},{1},{2} ", ReadSingle(), ReadSingle(), ReadSingle()); } if ((flags & 2) == 2) { Writer.Write("Rotation:{0},{1},{2} ", ReadSingle(), ReadSingle(), ReadSingle()); } if ((flags & 4) == 4) { Writer.Write("Scale:{0},{1},{2} ", ReadSingle(), ReadSingle(), ReadSingle()); } Writer.WriteLine("]"); } return; case "EngineQsTransform": { Writer.Write(" [ "); var flags = ReadByte(); if ((flags & 1) == 1) { Writer.Write("Posistion:{0},{1},{2} ", ReadSingle(), ReadSingle(), ReadSingle()); } if ((flags & 2) == 2) { Writer.Write("Rotation:{0},{1},{2},{3} ", ReadSingle(), ReadSingle(), ReadSingle(), ReadSingle()); } if ((flags & 4) == 4) { Writer.Write("Scale:{0},{1},{2} ", ReadSingle(), ReadSingle(), ReadSingle()); } Writer.WriteLine("]"); } return; case "TagList": { // This could be a vlq int value but so far there is no tag list // size big enough to use more than one bytes. var count = ReadByte(); var tags = new string[count]; for (var i = 0; i < count; i++) { tags[i] = names[ReadUInt16()].Value; } Writer.WriteLine(" [{0}]", string.Join(",", tags)); } return; case "EntityHandle": { /* * Read the first byte which will tell you what type of entity handle it is. * Values: * 0 - None - 0 bytes * 1 - Entity Guid - 32 bytes * 2 - IdTag - 17 bytes * * Then read off that variable type. * * IdTag: * 1 Byte - 0 = Static, 1 = Dynamic * 16 Bytes - Guid Value * Entity: * 16 Bytes - Guid Value * 16 Bytes - Unknown */ var handletype = ReadByte(); switch (handletype) { //Entity case 1: var eguid = new CGUID(ReadBytes(16)); var unkn = ReadBytes(16); Writer.WriteLine(" [Entity - {0}]", eguid.ToString()); break; //IdTag case 2: var dynamic = ReadBoolean(); var guid = new CGUID(ReadBytes(16)); if (dynamic) { Writer.WriteLine(" [Dynamic: {0}]", guid.ToString()); } else { Writer.WriteLine(" [Static: {0}]", guid.ToString()); } break; } } return; case "static": { var length = ReadUInt32(); arr = arr[1].Split(new char[] { ',' }, 2); Writer.WriteLine(" {0}", length); Writer.WriteLine("{0}{{", offset.Substring(1)); for (uint i = 0; i < length; i++) { Writer.Write("{0}Id {1}:", offset, i); ParseVariale(arr[1], size, $"\t{offset}"); } Writer.WriteLine("{0}}}", offset.Substring(1)); } return; case "CDateTime": { var datetime = new CDateTime(ReadUInt64()); Writer.WriteLine(" {0}.{1}", datetime.ToString(), datetime.Value.Millisecond); } return; case "SharedDataBuffer": { var datasize = ReadInt32(); var bytes = ReadBytes(datasize); Writer.WriteLine(" {0} bytes", datasize); } return; case "DataBuffer": { var datasize = ReadInt32(); var bytes = ReadBytes(datasize); Writer.WriteLine(" {0} bytes", datasize); } return; case "DeferredDataBuffer": { Writer.WriteLine(" {0}", ReadUInt16()); } return; case "SMeshTypeResourceLODLevel": { Writer.WriteLine(" {0}", ReadSingle()); } return; case "CPhysicalCollision": { var unknown = ReadUInt32(); var nameCount = ReadByte(); Writer.WriteLine(); Writer.WriteLine("{0}{{", offset.Substring(1)); Writer.WriteLine("{0}unknown Uint32 {1}", offset, unknown); Writer.WriteLine("{0}Types", offset); Writer.WriteLine("{0}{{", offset); for (byte i = 0; i < nameCount; i++) { Writer.WriteLine("\t{0}Id {1}: {2}", offset, i, names[ReadUInt16()].Value); } Writer.WriteLine("{0}}}", offset); Writer.WriteLine("{0}Bytes {1}", offset, String.Join(", ", ReadBytes(16))); Writer.WriteLine("{0}}}", offset.Substring(1)); } return; #endregion } //Detects types such as [7]Float etc... var regEx = Regex.Match(type, @"^\[([0-9]+)\]([\x00-\x7F]+)$"); if (regEx.Success) { var arraySize = ReadUInt32(); if (arraySize != Convert.ToUInt32(regEx.Groups[1].Value)) { throw new FormatException(); } Writer.WriteLine(" {0}", arraySize); Writer.WriteLine("{0}{{", offset.Substring(1)); for (uint i = 0; i < arraySize; i++) { Writer.Write("{0}Id {1}:", offset, i); ParseVariale(regEx.Groups[2].Value, size, $"\t{offset}"); } Writer.WriteLine("{0}}}", offset.Substring(1)); return; } var myType = AssemblyDictionary.GetTypeByName(type); if (myType != null && myType.IsEnum) { if (myType.IsDefined(typeof(FlagsAttribute), false)) { var values = new List <string>(); while (true) { var flag = ReadUInt16(); if (flag == 0) { break; } values.Add(names[flag].Value); } if (values.Count != 0) { Writer.WriteLine(" {0}", Enum.Parse(myType, String.Join(",", values))); } else { Writer.WriteLine(" {0}", "None"); } } else { var value = names[ReadUInt16()].Value; Writer.WriteLine(" {0}", value); } return; } Writer.WriteLine(); Writer.WriteLine("{0}{{", offset.Substring(1)); ReadVariable(offset); Writer.WriteLine("{0}}}", offset.Substring(1)); }
/// <summary> /// The instantiation step of the RedEngine-3 reflection. /// </summary> /// <param name="typename">Can be either a generic type such as CUint32 - then converted with GetWKitTypeFromREDType, or a complex type like a /// pointer to a class, a handle to an import file, an array, a soft reference, a static reference, various buffers, an enum.</param> /// <param name="varname">The variable name</param> /// <param name="cr2w">The cr2w base file</param> /// <param name="parentVariable">The class owning this attribute</param> /// <param name="readUnknownAsBytes"></param> /// <returns></returns> public static CVariable Create(string typename, string varname, CR2WFile cr2w, CVariable parentVariable, bool readUnknownAsBytes = true) { typename = REDReflection.GetWKitBaseTypeFromREDBaseType(typename); var fullname = typename; // check for normal type if (AssemblyDictionary.TypeExists(typename)) { var type = AssemblyDictionary.GetTypeByName(typename); if (type != null) { object instance = System.Activator.CreateInstance(type, cr2w, parentVariable, varname); return(instance as CVariable); } } // check for enum types if (AssemblyDictionary.EnumExists(typename)) { Enum e = (Enum)System.Activator.CreateInstance(AssemblyDictionary.GetEnumByName(typename)); var cenum = MakeGenericEnumType(typeof(CEnum <>), e); return(cenum); } else if (CR2WManager.EnumExists(typename)) { Enum e = (Enum)System.Activator.CreateInstance(CR2WManager.GetEnumByName(typename)); var cenum = MakeGenericEnumType(typeof(CEnum <>), e); return(cenum); } // check for generic type else if (typename.StartsWith('[')) { string generictype = typename.Substring(3); CVariable innerobject = Create(generictype, "", cr2w, null); var arrayacc = MakeArray(typeof(CArrayFixedSize <>), innerobject.GetType()); //arrayacc.Flags = new List<int>() { int.Parse(matchArrayType.Groups[1].Value) }; arrayacc.Elementtype = generictype; return(arrayacc as CVariable); } else if (typename.Contains(':')) { #region GENERIC TYPES string[] splits = typename.Split(':'); string generictype = splits.First(); string innertype = string.Join(":", splits.Skip(1)); // e.g. handle:CEntityTemplate switch (generictype) { case "CHandle": case "handle": { CVariable innerobject = Create(innertype, "", cr2w, null); return(MakeGenericType(typeof(CHandle <>), innerobject)); } case "wCHandle": case "whandle": { CVariable innerobject = Create(innertype, "", cr2w, null); return(MakeGenericType(typeof(wCHandle <>), innerobject)); } case "CrRef": case "rRef": { CVariable innerobject = Create(innertype, "", cr2w, null); return(MakeGenericType(typeof(rRef <>), innerobject)); } case "CraRef": case "raRef": { CVariable innerobject = Create(innertype, "", cr2w, null); return(MakeGenericType(typeof(raRef <>), innerobject)); } case "array": { // match pattern e.g. // array: (array:)Float // array of array: (array:)handle:meshMeshAppearance CVariable innerobject = Create(innertype, "", cr2w, null); IArrayAccessor arrayacc = MakeArray(typeof(CArray <>), innerobject.GetType()); arrayacc.Elementtype = innertype; return(arrayacc as CVariable); } case "static": { typename = generictype; // match pattern e.g. // static: (4),(Uint32) var regArrayType = new Regex(@"(\d+),(.+)"); var matchArrayType = regArrayType.Match(fullname); if (matchArrayType.Success) { CVariable innerobject = Create(matchArrayType.Groups[2].Value, "", cr2w, null); var arrayacc = MakeArray(typeof(CStatic <>), innerobject.GetType()); //arrayacc.Flags = new List<int>() { int.Parse(matchArrayType.Groups[1].Value) }; arrayacc.Elementtype = matchArrayType.Groups[2].Value; return(arrayacc as CVariable); } else { throw new InvalidParsingException($"Invalid static type format: typename: {typename}."); } } case "CEnum": { Enum innerobject = CreateEnum(innertype); return(MakeGenericEnumType(typeof(CEnum <>), innerobject)); } default: { throw new MissingTypeException(generictype); } } #endregion } else { // check if custom type if (CR2WManager.TypeExists(typename)) { var type = CR2WManager.GetTypeByName(typename); object instance = System.Activator.CreateInstance(type, cr2w, parentVariable, varname); return(instance as CVariable); } // this should never happen if (!cr2w.UnknownTypes.Contains(fullname)) { cr2w.UnknownTypes.Add(fullname); } if (readUnknownAsBytes) { return(new CBytes(cr2w, parentVariable, $"UNKNOWN:{typename}:{varname}")); } else { return(null); } } #region LOCAL FUNCTIONS IArrayAccessor MakeArray(Type arraytype, Type generictype) { Type elementType; if (arraytype == typeof(CStatic <>)) { elementType = typeof(CStatic <>).MakeGenericType(generictype); } else if (arraytype == typeof(CArrayFixedSize <>)) { elementType = typeof(CArrayFixedSize <>).MakeGenericType(generictype); } else if (arraytype == typeof(CArray <>)) { elementType = typeof(CArray <>).MakeGenericType(generictype); } else { throw new NotImplementedException(); } var array = System.Activator.CreateInstance(elementType, cr2w, parentVariable, varname) as CVariable; return(array as IArrayAccessor); } CVariable MakeGenericType(Type gentype, CVariable innerobject) { if (innerobject != null) { Type elementType = gentype.MakeGenericType(innerobject.GetType()); CVariable handle = System.Activator.CreateInstance(elementType, cr2w, parentVariable, varname) as CVariable; return(handle); } else { throw new Exception(); } } CVariable MakeGenericEnumType(Type gentype, Enum innerobject) { if (innerobject != null) { Type elementType = gentype.MakeGenericType(innerobject.GetType()); CVariable handle = System.Activator.CreateInstance(elementType, cr2w, parentVariable, varname) as CVariable; return(handle); } else { throw new Exception(); } } #endregion }
/// <summary> /// The instantiation step of the RedEngine-3 reflection. /// </summary> /// <param name="typename">Can be either a generic type such as CUint32 - then converted with GetWKitTypeFromREDType, or a complex type like a /// pointer to a class, a handle to an import file, an array, a soft reference, a static reference, various buffers, an enum.</param> /// <param name="varname">The variable name</param> /// <param name="cr2w">The cr2w base file</param> /// <param name="parentVariable">The class owning this attribute</param> /// <param name="readUnknownAsBytes"></param> /// <returns></returns> public static CVariable Create(string typename, string varname, CR2WFile cr2w, CVariable parentVariable, bool readUnknownAsBytes = true) { typename = REDReflection.GetWKitBaseTypeFromREDBaseType(typename); var fullname = typename; // check for normal type if (AssemblyDictionary.TypeExists(typename)) { var type = AssemblyDictionary.GetTypeByName(typename); if (type != null) { object instance = Activator.CreateInstance(type, cr2w, parentVariable, varname); return(instance as CVariable); } } // check for enum types if (AssemblyDictionary.EnumExists(typename)) { Enum e = (Enum)Activator.CreateInstance(AssemblyDictionary.GetEnumByName(typename)); var cenum = MakeGenericEnumType(typeof(CEnum <>), e); return(cenum); } else if (CR2WManager.EnumExists(typename)) { Enum e = (Enum)Activator.CreateInstance(CR2WManager.GetEnumByName(typename)); var cenum = MakeGenericEnumType(typeof(CEnum <>), e); return(cenum); } // check for generic type else if (typename.Contains(':')) { #region GENERIC TYPES string[] splits = typename.Split(':'); string generictype = splits.First(); string innertype = string.Join(":", splits.Skip(1)); // e.g. handle:CEntityTemplate switch (generictype) { case "CHandle": case "handle": { CVariable innerobject = Create(innertype, "", cr2w, null); return(MakeGenericType(typeof(CHandle <>), innerobject)); } case "CPtr": case "ptr": { CVariable innerobject = Create(innertype, "", cr2w, null); return(MakeGenericType(typeof(CPtr <>), innerobject)); } case "CSoft": case "soft": { CVariable innerobject = Create(innertype, "", cr2w, null); return(MakeGenericType(typeof(CSoft <>), innerobject)); } case "array": { // match pattern e.g. // array: Array: (2),(0),(handle:CBitmapTexture) // array: Array: (2),(0),(Int32) // array of array: Array: (2),(0),(Array:133,0,EngineQsTransform) string[] arraysplits = innertype.Split(','); string flag1 = arraysplits[0]; string flag2 = arraysplits[1]; string body = string.Join(",", arraysplits.Skip(2)); if (arraysplits.Length >= 3) { //byte arrays, these can be huge, using ordinary arrays is just too slow. if (body == "Uint8" || body == "Int8") { var bytearray = new CByteArray(cr2w, parentVariable, varname); // save the actual redengine type for serialization: e.g. array:2,0,Uint8 bytearray.InternalType = typename; return(bytearray); } // all other arrays CVariable innerobject = Create(body, "", cr2w, null); IArrayAccessor arrayacc = MakeArray(typeof(CArray <>), innerobject.GetType()); arrayacc.Flags = new List <int>() { int.Parse(flag1), int.Parse(flag2) }; if (innerobject is IArrayAccessor accessor && accessor.Flags != null) { arrayacc.Flags.AddRange(accessor.Flags); } arrayacc.Elementtype = body; return(arrayacc as CVariable); } else { CVariable innerobject = Create(innertype, "", cr2w, null); IArrayAccessor arrayacc = MakeArray(typeof(CArray <>), innerobject.GetType()); arrayacc.Elementtype = body; return(arrayacc as CVariable); } } case "static": { typename = generictype; // match pattern e.g. // static: (4),(Uint32) var regArrayType = new Regex(@"(\d+),(.+)"); var matchArrayType = regArrayType.Match(fullname); if (matchArrayType.Success) { CVariable innerobject = Create(matchArrayType.Groups[2].Value, "", cr2w, null); var arrayacc = MakeArray(typeof(CStatic <>), innerobject.GetType()); arrayacc.Flags = new List <int>() { int.Parse(matchArrayType.Groups[1].Value) }; arrayacc.Elementtype = matchArrayType.Groups[2].Value; return(arrayacc as CVariable); } else { throw new InvalidParsingException($"Invalid static type format: typename: {typename}."); } } case "CBufferUInt16": { CVariable innerobject = Create(innertype, "", cr2w, null); return(MakeGenericType(typeof(CBufferUInt16 <>), innerobject)); } case "CBufferUInt32": { CVariable innerobject = Create(innertype, "", cr2w, null); return(MakeGenericType(typeof(CBufferUInt32 <>), innerobject)); } case "CBufferVLQInt32": { CVariable innerobject = Create(innertype, "", cr2w, null); return(MakeGenericType(typeof(CBufferVLQInt32 <>), innerobject)); } case "CCompressedBuffer": { CVariable innerobject = Create(innertype, "", cr2w, null); return(MakeGenericType(typeof(CCompressedBuffer <>), innerobject)); } case "CPaddedBuffer": { CVariable innerobject = Create(innertype, "", cr2w, null); return(MakeGenericType(typeof(CPaddedBuffer <>), innerobject)); } case "CEnum": { Enum innerobject = CreateEnum(innertype); return(MakeGenericEnumType(typeof(CEnum <>), innerobject)); } default: { throw new NotImplementedException(); } } #endregion } else { #region FIXED SIZE ARRAYS // match pattern e.g. // [(1)](Bezier2dHandle) var regFixedSizeArray = new Regex(@"^\[(\d+)\](.+)$"); var matchFixedSizeArray = regFixedSizeArray.Match(typename); if (matchFixedSizeArray.Success) { CVariable innerobject = Create(matchFixedSizeArray.Groups[2].Value, "", cr2w, null); var arrayacc = MakeArray(typeof(CArrayFixedSize <>), innerobject.GetType()); arrayacc.Flags = new List <int>() { int.Parse(matchFixedSizeArray.Groups[1].Value) }; arrayacc.Elementtype = matchFixedSizeArray.Groups[2].Value; return(arrayacc as CVariable); } #endregion if (fullname.Contains("@SItem")) { cr2w.UnknownTypes.Add($"Congratulations! You have found one of the hidden e3 files! These files are special." + $" If you edited this file and are experiencing errors, please contact a member of the Wkit Team. ErrorCode: {fullname}"); return(new SItem(cr2w, parentVariable, varname)); } else if (fullname.Contains("#CEnvironmentDefinition")) { cr2w.UnknownTypes.Add($"Congratulations! You have found one of the hidden e3 files! These files are special." + $" If you edited this file and are experiencing errors, please contact a member of the Wkit Team. ErrorCode: {fullname}"); return(new CHandle <CEnvironmentDefinition>(cr2w, parentVariable, varname)); } else { // check if custom type if (CR2WManager.TypeExists(typename)) { var type = CR2WManager.GetTypeByName(typename); object instance = Activator.CreateInstance(type, cr2w, parentVariable, varname); return(instance as CVariable); } // this should never happen if (!cr2w.UnknownTypes.Contains(fullname)) { cr2w.UnknownTypes.Add(fullname); } if (readUnknownAsBytes) { return(new CBytes(cr2w, parentVariable, $"UNKNOWN:{typename}:{varname}")); } else { return(null); } } } #region LOCAL FUNCTIONS IArrayAccessor MakeArray(Type arraytype, Type generictype) { Type elementType; if (arraytype == typeof(CStatic <>)) { elementType = typeof(CStatic <>).MakeGenericType(generictype); } else if (arraytype == typeof(CArrayFixedSize <>)) { elementType = typeof(CArrayFixedSize <>).MakeGenericType(generictype); } else if (arraytype == typeof(CArray <>)) { elementType = typeof(CArray <>).MakeGenericType(generictype); } else { throw new NotImplementedException(); } var array = Activator.CreateInstance(elementType, cr2w, parentVariable, varname) as CVariable; return(array as IArrayAccessor); } CVariable MakeGenericType(Type gentype, CVariable innerobject) { if (innerobject != null) { Type elementType = gentype.MakeGenericType(innerobject.GetType()); CVariable handle = Activator.CreateInstance(elementType, cr2w, parentVariable, varname) as CVariable; return(handle); } else { throw new Exception(); } } CVariable MakeGenericEnumType(Type gentype, Enum innerobject) { if (innerobject != null) { Type elementType = gentype.MakeGenericType(innerobject.GetType()); CVariable handle = Activator.CreateInstance(elementType, cr2w, parentVariable, varname) as CVariable; return(handle); } else { throw new Exception(); } } #endregion }