protected override void Parse(ref ByteStreamReader bsr) { IdString = bsr.ReadStringOfLength(4); SaveVersion = bsr.ReadSInt(); TokenTableFileTableOffset = bsr.ReadSInt(); TokenCount = bsr.ReadSInt(); TokenTableSize = bsr.ReadSInt(); // offset += table size? }
// CSaveRestore::RestoreClientState // id = 'V' 'A' 'L' 'V', version = 0x73 = 115, section header = 2 protected override unsafe void Parse(ref ByteStreamReader bsr) { base.Parse(ref bsr); var version = bsr.ReadSInt(); var magic = bsr.ReadSInt(); // if ( magicnumber == SECTION_MAGIC_NUMBER ) var sectionHeaderVersion = bsr.ReadSInt(); bsr.ReadStruct(out BaseClientSections sections, sizeof(BaseClientSections)); //var symbolTable = bsr.ReadSymbolTable(sections.SymbolCount, sections.SymbolSize); var symbolTable = bsr.ReadNullSeparatedStrings(sections.SymbolCount); }
public static EventsSave Restore(TypeDesc typeDesc, SaveInfo info, ref ByteStreamReader bsr) { int count = bsr.ReadSInt(); // inline version of reading embedded field of type CBaseEntityOutput (it only contains 1 field) if (bsr.ReadSShort() != 4) { throw new ConstraintException("first entry in data map should be 4"); } string?mapSym = bsr.ReadSymbol(info); if (mapSym != "Value") { throw new ConstraintException($"bad symbol, expected \"Value\" but read \"{mapSym}\""); } int fieldsSaved = bsr.ReadSInt(); ParsedSaveField?psf = null; if (fieldsSaved == 1) { bsr.StartBlock(info, out string?sym); if (sym != "m_Value") { throw new ConstraintException($"bad symbol, expected \"m_Value\" but read \"{sym}\""); } FieldType type = (FieldType)bsr.ReadSInt(); string? s = FieldNameFromType(type); if (s != null) { TypeDesc t = new TypeDesc(s, type); DataMap m = new DataMap("m_Value", new [] { t }); var pm = bsr.ReadDataMap(m, info); if (pm.ParsedFields.Any()) { psf = pm.ParsedFields.Single().Value; } } bsr.EndBlock(info); } else if (fieldsSaved != 0) { throw new ConstraintException($"expected 0 fields, got {fieldsSaved}"); } ParsedDataMap[] events = new ParsedDataMap[count]; for (int i = 0; i < count; i++) { events[i] = bsr.ReadDataMap("EntityOutput", info); } return(new EventsSave(typeDesc, psf, events)); }
protected override void Parse(ref ByteStreamReader bsr) { int nEntities = bsr.ReadSInt(); EntHeaders = new ParsedDataMap[nEntities]; for (int i = 0; i < nEntities; i++) { EntHeaders[i] = bsr.ReadDataMap("ETABLE", SaveInfo); } }
protected override void Parse(ref ByteStreamReader bsr) { SourceFileHeader = new SourceFileHeader(this); SourceFileHeader.ParseStream(ref bsr); SaveInfo.ParseContext.CurrentSymbolTable = bsr.ReadSymbolTable(SourceFileHeader.TokenCount, SourceFileHeader.TokenTableSize) !; GameHeader = bsr.ReadDataMap("GameHeader", SaveInfo); Globals = bsr.ReadDataMap("GLOBAL", SaveInfo); StateFiles = new EmbeddedStateFile[bsr.ReadSInt()]; for (int i = 0; i < StateFiles.Length; i++) { StateFiles[i] = EmbeddedStateFile.CreateFromName(this, bsr.ReadCharArray(260)); int fileLength = bsr.ReadSInt(); StateFiles[i].ParseStream(bsr.SplitAndSkip(fileLength)); } SaveInfo.Cleanup(); Debug.Assert(bsr.BytesRemaining == 0); SaveInfo.PrintDeterminedDatamaps(); }
/* This pretty much exactly what the game does. A datamap is created dynamically which contains a description * for each key/value of the map. * Custom params: * [0] - the field type of each key * [1] - the custom read function of each key (if applicable) * [2] - the embedded map of each key (if applicable) * [3] - the field type of each value * [4] - the custom read function of each value (if applicable) * [5] - the embedded map of each value (if applicable) * */ public static UtilMap <TK, TV> Restore(TypeDesc mapDesc, SaveInfo info, ref ByteStreamReader bsr) { object[] @params = mapDesc.CustomParams !; DataMap? embKeyMap = @params[2] is string sk ? info.SDataMapLookup[sk] : null; DataMap? embValMap = @params[5] is string sv ? info.SDataMapLookup[sv] : null; TypeDesc keyDesc = new TypeDesc( name: "K", flags: DescFlags.FTYPEDESC_SAVE, fieldType: (FieldType)@params[0], customReadFunc: (CustomReadFunc?)@params[1], numElements: 1) { EmbeddedMap = embKeyMap }; TypeDesc valDesc = new TypeDesc( name: "T", // std::map<Key, T> flags: DescFlags.FTYPEDESC_SAVE, fieldType: (FieldType)@params[3], customReadFunc: (CustomReadFunc?)@params[4], numElements: 1) { EmbeddedMap = embValMap }; DataMap vecMap = new DataMap("um", new[] { keyDesc, valDesc }); bsr.StartBlock(info); int count = bsr.ReadSInt(); var res = new KeyValuePair <ParsedSaveField <TK>, ParsedSaveField <TV> > [count]; for (int i = 0; i < count; i++) { ParsedDataMap readResult = bsr.ReadDataMap(vecMap, info); var k = (ParsedSaveField <TK>)readResult.ParsedFields["K"]; var v = (ParsedSaveField <TV>)readResult.ParsedFields["T"]; res[i] = new KeyValuePair <ParsedSaveField <TK>, ParsedSaveField <TV> >(k, v); } bsr.EndBlock(info); return(new UtilMap <TK, TV>(mapDesc, res, keyDesc, valDesc)); }
/* This pretty much exactly what the game does. A datamap is created dynamically which contains only a single * description for each element of this vector. This solution means I only have to do a single cast. * Custom params: * [0] - the field type of each element * [1] - the custom read function of each element (if applicable) * [2] - the embedded map of each element (if applicable) * */ public static UtilVector <T> Restore(TypeDesc vecDesc, SaveInfo info, ref ByteStreamReader bsr) { object[] @params = vecDesc.CustomParams !; DataMap?embMap = @params[2] is string s ? info.SDataMapLookup[s] : null; int count = bsr.ReadSInt(); TypeDesc elemDesc = new TypeDesc( name: "elems", flags: DescFlags.FTYPEDESC_SAVE, fieldType: (FieldType)@params[0], customReadFunc: (CustomReadFunc?)@params[1], numElements: (ushort)(embMap == null ? count : 1)) { EmbeddedMap = embMap }; // Sometimes the count is one but the read result does not have an element. I'm not sure if this is // intended or not but by default that will cause an exception. DataMap vecMap = new DataMap(embMap == null ? "elems" : "uv", new[] { elemDesc }); T[] res; if (embMap == null && count > 1) { ParsedDataMap mapReadResult = bsr.ReadDataMap(vecMap, info); res = (ParsedSaveField <T[]>)mapReadResult.ParsedFields.Single().Value; } else // if the field type is embedded then the elements are read one by one { res = new T[count]; for (int i = 0; i < count; i++) { ParsedDataMap mapReadResult = bsr.ReadDataMap(vecMap, info); res[i] = (ParsedSaveField <T>)mapReadResult.ParsedFields.Single().Value; } } return(new UtilVector <T>(res, elemDesc, vecDesc)); }
private static ParsedSaveField VGuiScreenStringOps(TypeDesc desc, SaveInfo info, ref ByteStreamReader bsr) => new ParsedSaveField <string>(bsr.ReadStringOfLength(bsr.ReadSInt()), desc);
static ParsedSaveField ReadFunc(TypeDesc typeDesc, SaveInfo info, ref ByteStreamReader bsr) => new ParsedSaveField <int>(bsr.ReadSInt(), typeDesc);
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; }
static ParsedSaveField MatReadFunc(TypeDesc desc, SaveInfo info, ref ByteStreamReader bsr) => new ParsedSaveField <MaterialIndexStr>((MaterialIndexStr)bsr.ReadStringOfLength(bsr.ReadSInt()), desc);