public ParsedDataMap ReadDataMap(DataMap map, SaveInfo info) { if (ReadSShort() != 4) { throw new ConstraintException($"bad first value while parsing datamap \"{map.ClassName}\", expected 4"); } string sym = ReadSymbol(info) !; if (sym != map.DataMapName) { info.SDataMapLookup.TryGetValue(sym, out DataMap? cmpMap); if (!ReferenceEquals(cmpMap, map)) { DetermineDataMapHierarchy(info, $"\"{sym}\" does not match \"{map.DataMapName}\"", AbsoluteByteIndex - 4); throw new ArgumentException($"bad symbol, expected \"{map.DataMapName}\" but read \"{sym}\""); } } int fieldsSaved = ReadSInt(); ParsedDataMap ret = new ParsedDataMap(map, fieldsSaved); for (int i = 0; i < fieldsSaved; i++) { StartBlock(info, out short byteSize, out string?s); map.FieldDict.TryGetValue(s !, out TypeDesc? curFieldDesc); if (curFieldDesc != null) { if (!curFieldDesc.Placeholder) { try { int index = AbsoluteByteIndex; ParsedSaveField?f = ReadSaveField(curFieldDesc !, info, byteSize); f?.SetIndex(index); // I allow returning null here for the vphys read EndBlock(info); // try ending the block to see if we read this correctly ret.AddSaveField(f); } catch (Exception e) { info.AddError($"exception while reading field {s} from datamap \"{map.ClassName}\": {e.Message}"); SkipCurrentBlock(info); } } else { DetermineDataMapHierarchy(info, $"placeholder field \"{curFieldDesc.Name}\"", AbsoluteByteIndex); SkipCurrentBlock(info); } } else { info.AddError($"skipping field \"{s}\" from datamap \"{map.ClassName}\" ({byteSize} bytes), no appropriate field found"); SkipCurrentBlock(info); } } return(ret); }
private static readonly HashSet<string> Searched = new HashSet<string>(); // for debugging protected override void Parse(ref ByteStreamReader bsr) { EntData = new ParsedEntData[DataHeader.EntHeaders.Length]; for (int i = 0; i < DataHeader.EntHeaders.Length; i++) { ParsedDataMap entHeader = DataHeader.EntHeaders[i]; var edictIndex = entHeader.GetFieldOrDefault<int>("edictindex"); bsr.CurrentByteIndex = entHeader.GetFieldOrDefault<int>("location"); string? className = entHeader.GetFieldOrDefault<string>("classname"); if (className == null) // todo continue; if (!SaveInfo.SDataMapLookup.TryGetValue(className, out DataMap? entMap)) { string s = $"{nameof(EntitySaveStateBlock)}.{nameof(Parse)} - datamap for \"{className}\" not found"; if (bsr.ReadSShort() == 4 && Searched.Add(s)) { bsr.DetermineDataMapHierarchy(SaveInfo, $"{nameof(EntitySaveStateBlock)}.{nameof(Parse)} - datamap for \"{className}\" not found", bsr.AbsoluteByteIndex - 2); } SaveInfo.AddError(s #if DEBUG ,false #endif ); continue; } EntData[i] = EntDataFactory.CreateFromName(SaveRef!, entHeader, entMap); SaveInfo.ParseContext.CurrentEntity = EntData[i]; EntData[i]!.ParseStream(ref bsr); } }
public static SaveGameHeader?CreateFromHeaderInfo(SourceSave?saveRef, ParsedDataMap dataHeader) { CharArray name = dataHeader.GetField <CharArray>("szName"); switch (name) { case "Entities": return(new ETableHeader(saveRef, dataHeader)); case "Physics": return(new PhysicsInfoHeader(saveRef, dataHeader)); case "AI": case "Templates": case "ResponseSystem": case "Commentary": case "EventQueue": case "Achievement": return(new VersionableSaveGameHeader(saveRef, dataHeader)); default: saveRef !.SaveInfo.AddError($"unknown header name: {name}"); return(null); // todo VScriptServer and maybe PaintDatabase (will have to ree) } }
protected override void Parse(ref ByteStreamReader bsr) { try { ParsedFields = bsr.ReadDataMapRecursive(ClassMap, SaveInfo); } catch (Exception e) { SaveInfo.AddError($"exception while parsing map \"{ClassMap.ClassName}\": {e.Message}"); } }
public bool TryReadDataMapRecursive(string dataMapName, SaveInfo info, out ParsedDataMap?result) { if (TryGetMapFromString(dataMapName, info, out DataMap? map)) { try { result = ReadDataMapRecursive(map !, info); return(true); } catch (Exception e) { info.AddError($"exception while reading datamap \"{dataMapName}\" recursively: {e.Message}"); } } result = null; return(false); }
protected override void Parse(ref ByteStreamReader bsr) { base.Parse(ref bsr); Version = bsr.ReadSInt(); int nBytesSymbols = bsr.ReadSInt(); int nSymbols = bsr.ReadSInt(); int nBytesDataHeaders = bsr.ReadSInt(); int nBytesData = bsr.ReadSInt(); SaveInfo.ParseContext.CurrentSymbolTable = bsr.ReadSymbolTable(nSymbols, nBytesSymbols) !; int @base = bsr.CurrentByteIndex; int sizeHeaders = bsr.ReadSInt(); int sizeBodies = bsr.ReadSInt(); // info about the header block BlockHeadersInfo = UtilVector <ParsedDataMap> .RestoreEmbedded("BlockHeadersInfo", "SaveRestoreBlockHeader_t", SaveInfo, ref bsr); SaveGameHeaders = new List <SaveGameHeader>(BlockHeadersInfo.Count); // read the headers one by one foreach (ParsedDataMap headerInfo in BlockHeadersInfo) { int loc = headerInfo.GetField <int>("locHeader"); if (loc == -1) { continue; } bsr.CurrentByteIndex = @base + loc; SaveGameHeader?sgh = SaveGameHeader.CreateFromHeaderInfo(SaveRef, headerInfo); if (sgh == null) { continue; } sgh.ParseStream(ref bsr); SaveGameHeaders.Add(sgh); } //@base = bsr.CurrentByteIndex = @base + sizeHeaders; ByteStreamReader bodyBase = bsr.Split(); // block data is offset from this location SaveHeader = bsr.ReadDataMap("Save Header", SaveInfo); SaveInfo.BaseTime = SaveHeader.GetFieldOrDefault <Time>("time__USE_VCR_MODE"); //SaveInfo.LandmarkPos // todo gotten from adjacency list? @base = bsr.CurrentByteIndex; int connections = SaveHeader.GetFieldOrDefault <int>("connectionCount"); // to other maps? int lightStyles = SaveHeader.GetFieldOrDefault <int>("lightStyleCount"); if (connections > 0) { AdjacencyList = new ParsedDataMap[connections]; for (int i = 0; i < connections; i++) { AdjacencyList[i] = bsr.ReadDataMap("ADJACENCY", SaveInfo); } } if (lightStyles > 0) { LightStyleList = new ParsedDataMap[lightStyles]; for (int i = 0; i < lightStyles; i++) { LightStyleList[i] = bsr.ReadDataMap("LIGHTSTYLE", SaveInfo); } } @base = bsr.CurrentByteIndex; Blocks = new List <SaveStateBlock>(SaveGameHeaders.Count); // now read the actual blocks of data based off of information from the headers foreach (SaveGameHeader header in SaveGameHeaders) { int loc = header.DataHeader.GetFieldOrDefault <int>("locBody"); if (loc == -1) { continue; } //bodyBase.CurrentByteIndex = loc; //bsr.CurrentByteIndex = @base; if (!SaveStateBlock.CreateFromHeader(SaveRef !, header, out SaveStateBlock blockHandler)) { SaveInfo.AddError($"{nameof(SaveStateBlock)} not created from header: \"{header.Name}\""); continue; } blockHandler.ParseStream(ref bodyBase); Blocks.Add(blockHandler); } //bsr.CurrentByteIndex = @base + sizeBodies; }