// all of these generic types must* stay consistent with TypeDesc.GetNetTypeFromFieldType private ParsedSaveField?ReadSaveField(TypeDesc desc, SaveInfo info, int bytesAvail) { switch (desc.FieldType) { case EMBEDDED: if (desc.NumElements == 1) { return(new ParsedSaveField <ParsedDataMap>(ReadDataMapRecursive(desc.EmbeddedMap !, info), desc)); } else { ParsedDataMap[] parsedMaps = new ParsedDataMap[desc.NumElements]; for (int i = 0; i < desc.NumElements; i++) { parsedMaps[i] = ReadDataMapRecursive(desc.EmbeddedMap !, info); } return(new ParsedSaveField <ParsedDataMap[]>(parsedMaps, desc, parsedMaps.Length)); } case CUSTOM: return(desc.InvokeCustomReadFunc(ref this, info)); // this can return null case MODELNAME: return(ReadSimpleString(desc, bytesAvail, s => (ModelName)s)); case SOUNDNAME: return(ReadSimpleString(desc, bytesAvail, s => (SoundName)s)); case FUNCTION: return(ReadSimpleString(desc, bytesAvail, s => (Func)s)); case STRING: return(ReadSimpleString(desc, bytesAvail)); case MODELINDEX: return(ReadSimpleString(desc, bytesAvail, s => (ModelIndex)s)); case MATERIALINDEX: return(ReadSimple <int, MaterialIndex>(desc, bytesAvail, i => (MaterialIndex)i)); case FLOAT: return(ReadSimple <float>(desc, bytesAvail)); case VECTOR2D: return(ReadSimple <Vector2>(desc, bytesAvail)); case VECTOR: return(ReadSimple <Vector3>(desc, bytesAvail)); case POSITION_VECTOR: return(ReadSimple <Vector3>(desc, bytesAvail, vec => vec + info.LandmarkPos)); case QUATERNION: return(ReadSimple <Vector4>(desc, bytesAvail)); case EHANDLE: return(ReadSimple <int, Ehandle>(desc, bytesAvail, i => (Ehandle)i)); case CLASSPTR: return(ReadSimple <int, ClassPtr>(desc, bytesAvail, i => (ClassPtr)i)); case EDICT: return(ReadSimple <int, Edict>(desc, bytesAvail, i => (Edict)i)); case INTEGER: return(ReadSimple <int>(desc, bytesAvail)); case BOOLEAN: return(ReadSimple <byte, bool>(desc, bytesAvail, b => b != 0)); case SHORT: return(ReadSimple <short>(desc, bytesAvail)); case BYTE: return(ReadSimple <byte>(desc, bytesAvail)); case INTERVAL: return(ReadSimple <Interval>(desc, bytesAvail)); case CHARACTER: return(desc.NumElements == 1 ? ReadSimple <byte, char>(desc, bytesAvail, b => (char)b) : new ParsedSaveField <CharArray>(ReadCharArray(bytesAvail), desc, bytesAvail)); case COLOR32: return(ReadSimple <int, Color32>(desc, bytesAvail, i => (Color32)i)); case TIME: return(ReadSimple <float, Time>(desc, bytesAvail, f => { if (f == ZERO_TIME) { return (Time)0; } if (f != INVALID_TIME && f != FLT_MAX) { return (Time)(f + info.BaseTime); } return (Time)f; })); case TICK: int baseTick = info.TimeToTicks(info.BaseTime + 0.1f); return(ReadSimple <int, Tick>(desc, bytesAvail, i => (Tick)(i == TICK_NEVER_THINK_ENCODE ? TICK_NEVER_THINK : i + baseTick))); case VMATRIX: return(ReadSimple <VMatrix>(desc, bytesAvail)); case VMATRIX_WORLDSPACE: return(ReadSimple <VMatrix>(desc, bytesAvail, mat => { mat.ApplyTranslation(in info.LandmarkPos); return mat; }));