From 06dad2be97026a4d2cd99f0b2bc7a90ab586dd1d Mon Sep 17 00:00:00 2001 From: Angel Date: Fri, 4 Sep 2026 11:53:25 +0200 Subject: [PATCH 01/13] Implement the non-generic IList members of Array --- Datamodel.NET/Arrays.cs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Datamodel.NET/Arrays.cs b/Datamodel.NET/Arrays.cs index e51d6cd..b2dd2bf 100644 --- a/Datamodel.NET/Arrays.cs +++ b/Datamodel.NET/Arrays.cs @@ -82,15 +82,19 @@ public void CopyTo(T[] array, int offset) bool ICollection.IsReadOnly { get { return false; } } - public bool IsFixedSize => throw new NotImplementedException(); + public bool IsFixedSize => false; - public bool IsReadOnly => throw new NotImplementedException(); + public bool IsReadOnly => false; - public bool IsSynchronized => throw new NotImplementedException(); + public bool IsSynchronized => false; - public object SyncRoot => throw new NotImplementedException(); + public object SyncRoot => Inner; - object? IList.this[int index] { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } + object? IList.this[int index] + { + get => this[index]; + set => this[index] = value is null ? throw new InvalidOperationException("Trying to set a null object") : (T)value; + } public bool Remove(T item) => Inner.Remove(item); From d40f2619867d56767fe42837569592165a07c9a4 Mon Sep 17 00:00:00 2001 From: Angel Date: Fri, 4 Sep 2026 11:53:25 +0200 Subject: [PATCH 02/13] Fix the type check when assigning attributes to class properties --- Datamodel.NET/AttributeList.cs | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/Datamodel.NET/AttributeList.cs b/Datamodel.NET/AttributeList.cs index e5c912d..1f4582f 100644 --- a/Datamodel.NET/AttributeList.cs +++ b/Datamodel.NET/AttributeList.cs @@ -282,17 +282,10 @@ public virtual object? this[string name] { if (prop.CanWrite) { - // were actually fine with this being null, it will just set the value to null - // but need to check so the type check doesn't fail if it is null - if (value != null) + // null is fine, it will just set the value to null + if (value != null && !prop.PropertyType.IsInstanceOfType(value)) { - var valueType = value.GetType(); - - // types must be equal, or a superclass - if (prop.PropertyType != typeof(Element) && valueType.IsSubclassOf(prop.PropertyType)) - { - throw new InvalidDataException($"class property '{prop.Name}' with type '{prop.PropertyType}' does not match the type '{valueType}' of the value being set, this is likely a mismatch between the real class and the class from the datamodel"); - } + throw new InvalidDataException($"class property '{prop.DeclaringType!.Name}.{prop.Name}' with type '{prop.PropertyType}' can not hold a value of type '{value.GetType()}' (attribute '{name}'), this is likely a mismatch between the real class and the class from the datamodel"); } prop.SetValue(this, value); @@ -308,16 +301,16 @@ public virtual object? this[string name] if (existingArray.Count == 0) { existingArray.AddRange(incomingArray); - return; } else { throw new InvalidOperationException($"Attribute '{name}' modifies property {prop.DeclaringType!.Name}.{prop.Name}, which is write only and can't be replaced."); } } - - - throw new InvalidDataException("Property of deserialisation class must be writeable, make sure it's public and has a public setter"); + else + { + throw new InvalidDataException($"Property '{prop.DeclaringType!.Name}.{prop.Name}' of deserialisation class must be writeable, make sure it's public and has a public setter"); + } } return; @@ -432,6 +425,9 @@ public int Count /// public object SyncRoot { get { return Attribute_ChangeLock; } } + /// + /// Enumerates every attribute to be written by a codec: class properties first, in declaration order, followed by the plain attributes in the order they were added. + /// public IEnumerable GetAllAttributesForSerialization() { foreach (var attr in GetPropertyBasedAttributes(useSerializationName: true)) From 48ae92a28da2adf6a583b2ccb89f7ffdb9ec46d3 Mon Sep 17 00:00:00 2001 From: Angel Date: Fri, 4 Sep 2026 11:53:26 +0200 Subject: [PATCH 03/13] Resolve binary element references through the codec's element list --- Datamodel.NET/Codecs/Binary.cs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/Datamodel.NET/Codecs/Binary.cs b/Datamodel.NET/Codecs/Binary.cs index 8a33d8a..fc79905 100644 --- a/Datamodel.NET/Codecs/Binary.cs +++ b/Datamodel.NET/Codecs/Binary.cs @@ -21,6 +21,11 @@ class Binary : IDeferredAttributeCodec static readonly Dictionary SupportedAttributes = []; BinaryReader? Reader; + /// + /// Elements in the order the stream declares them. Element references are indices into this list, which must not change for deferred loading. + /// + readonly List ElementIndex = []; + /// /// The number of Datamodel binary ticks in one second. Used to store TimeSpan values. /// @@ -322,7 +327,10 @@ public void Encode(Datamodel dm, string encoding, int encoding_version, Stream s return dm.AllElements[id] ?? new Element(dm, id); } - return dm.AllElements[index]; + if (index < 0 || index >= ElementIndex.Count) + throw new CodecException($"Element index {index} is out of range."); + + return ElementIndex[index]; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -416,16 +424,18 @@ public Datamodel Decode(string encoding, int encoding_version, string format, in var id_bits = Reader.ReadBytes(16); var id = new Guid(BitConverter.IsLittleEndian ? id_bits : id_bits.Reverse().ToArray()); - if (!CodecUtilities.TryConstructCustomElement(elementFactory, reflectionParams, dm, type, name, id, out _)) + if (!CodecUtilities.TryConstructCustomElement(elementFactory, reflectionParams, dm, type, name, id, out var elem)) { // note: constructing an element, adds it to the datamodel.AllElements - _ = new Element(dm, name, id, type); + elem = new Element(dm, name, id, type); } + + ElementIndex.Add(elem!); } // read attributes (or not, if we're deferred) - foreach (var elem in dm.AllElements.ToArray()) + foreach (var elem in ElementIndex) { // assert if stub Debug.Assert(!elem.Stub); From 4ae949822157da65f7ef3cdac32ca08e99a24bfd Mon Sep 17 00:00:00 2001 From: Angel Date: Fri, 4 Sep 2026 11:53:39 +0200 Subject: [PATCH 04/13] Write prefix attributes in the binary encoding --- Datamodel.NET/Codecs/Binary.cs | 142 +++++++++++++++++++------ Datamodel.NET/Datamodel.ElementList.cs | 24 +++++ Datamodel.NET/Datamodel.cs | 6 ++ 3 files changed, 141 insertions(+), 31 deletions(-) diff --git a/Datamodel.NET/Codecs/Binary.cs b/Datamodel.NET/Codecs/Binary.cs index fc79905..7b3a6ab 100644 --- a/Datamodel.NET/Codecs/Binary.cs +++ b/Datamodel.NET/Codecs/Binary.cs @@ -171,6 +171,19 @@ public StringDictionary(int encoding_version, BinaryWriter writer, Datamodel dm, Scraped = []; ScrapeElement(dm.Root); + + // the prefix attributes are also written as a regular element in version 9 + if (EncodingVersion >= 9 && dm.PrefixAttributes.Count > 0) + { + AddString(string.Empty); + AddString(PrefixElementClass); + foreach (var attr in dm.PrefixAttributes) + { + AddString(attr.Key); + if (attr.Value is string stringValue) + AddString(stringValue); + } + } } } @@ -457,9 +470,24 @@ public Datamodel Decode(string encoding, int encoding_version, string format, in } } + // version 9 also stores the prefix attributes as an unreferenced element right after the root, fold it back in + if (EncodingVersion >= 9 && dm.PrefixAttributes.Count > 0 && dm.AllElements.Count > 1) + { + var duplicate = dm.AllElements[1]; + + if (duplicate != null && !duplicate.Stub && duplicate.ClassName == PrefixElementClass && duplicate.Name.Length == 0 + && duplicate.Keys.SequenceEqual(dm.PrefixAttributes.Keys)) + { + dm.PrefixElementId = duplicate.ID; + dm.AllElements.RemoveUnreferenced(duplicate); + } + } + return dm; } + const string PrefixElementClass = "DmElement"; + int EncodingVersion; public object? DeferredDecodeAttribute(Datamodel dm, long offset) @@ -563,7 +591,7 @@ void SkipAttribute(BinaryReader reader) readonly struct Encoder { readonly Dictionary ElementIndices; - readonly List ElementOrder; + readonly List ElementOrder; readonly BinaryWriter Writer; readonly StringDictionary StringDict; readonly Datamodel Datamodel; @@ -589,20 +617,30 @@ public void Encode() Writer.Write(string.Format(CodecUtilities.HeaderPattern, "binary", EncodingVersion, Datamodel.Format, Datamodel.FormatVersion) + "\n"); if (EncodingVersion >= 9) - Writer.Write(0); // Prefix elements + { + WritePrefixAttributes(); + } StringDict.WriteSelf(Writer); + var hasPrefixElement = EncodingVersion >= 9 && Datamodel.PrefixAttributes.Count > 0; + var elementCount = CountChildren(Datamodel.Root, []) + (hasPrefixElement ? 1 : 0); + Writer.Write(elementCount); + + var root = Datamodel.Root; + if (root != null && !root.Stub) { - var counter = new HashSet(); - var elementCount = CountChildren(Datamodel.Root, counter); + WriteIndexEntry(root, root.ClassName, root.Name, root.ID); - Writer.Write(elementCount); + // the prefix attributes are also stored as an unreferenced element right after the root + if (hasPrefixElement) + WriteIndexEntry(Datamodel.PrefixAttributes, PrefixElementClass, string.Empty, Datamodel.PrefixElementId); + + WriteIndexChildren(root); } - WriteIndex(Datamodel.Root); - foreach (var e in ElementOrder) - WriteBody(e); + foreach (var body in ElementOrder) + WriteBody(body); } int CountChildren(Element? elem, HashSet counter) @@ -635,16 +673,26 @@ int CountChildren(Element? elem, HashSet counter) void WriteIndex(Element? elem) { - if (elem is null || elem.Stub) return; + if (elem is null || elem.Stub || ElementIndices.ContainsKey(elem)) return; - ElementIndices[elem] = ElementIndices.Count; - ElementOrder.Add(elem); + WriteIndexEntry(elem, elem.ClassName, elem.Name, elem.ID); + WriteIndexChildren(elem); + } - StringDict.WriteString(elem.ClassName, Writer); - if (EncodingVersion >= 4) StringDict.WriteString(elem.Name, Writer); - else Writer.Write(elem.Name); - Writer.Write(elem.ID.ToByteArray()); + void WriteIndexEntry(AttributeList body, string className, string name, Guid id) + { + if (body is Element elem) + ElementIndices[elem] = ElementOrder.Count; + ElementOrder.Add(body); + StringDict.WriteString(className, Writer); + if (EncodingVersion >= 4) StringDict.WriteString(name, Writer); + else Writer.Write(name); + Writer.Write(id.ToByteArray()); + } + + void WriteIndexChildren(Element elem) + { foreach (var attr in Context.Attributes[elem]) { var child_elem = attr.Value as Element; @@ -666,31 +714,63 @@ void WriteIndex(Element? elem) } } - void WriteBody(Element elem) + /// + /// Prefix attributes are stored as a list of prefix elements, each a list of name/typed value pairs. + /// Only the first prefix element is read back, so everything is written into a single one. + /// + void WritePrefixAttributes() + { + var prefixAttributes = Datamodel.PrefixAttributes.Where(attr => attr.Value != null).ToArray(); + + if (prefixAttributes.Length == 0) + { + Writer.Write(0); + return; + } + + Writer.Write(1); + Writer.Write(prefixAttributes.Length); + + foreach (var attr in prefixAttributes) + { + Writer.Write(attr.Key); + WriteTypedValue(attr.Value, raw_string: true); + } + } + + void WriteBody(AttributeList elem) { - var attributesIterated = Context.Attributes[elem]; - //Writer.Write(elem.Count); + var attributesIterated = elem is Element element ? Context.Attributes[element] : elem.GetAllAttributesForSerialization().ToArray(); Writer.Write(attributesIterated.Length); foreach (var attr in attributesIterated) { StringDict.WriteString(attr.Key, Writer); - var attr_type = attr.Value == null ? typeof(Element) : attr.Value.GetType(); - var attr_type_id = TypeToId(attr_type, EncodingVersion); - Writer.Write(attr_type_id); + WriteTypedValue(attr.Value, raw_string: false); + } + } - if (attr.Value == null || !Datamodel.IsDatamodelArrayType(attr.Value.GetType())) - WriteAttribute(attr.Value, false); - else - { - var array = (System.Collections.IList)attr.Value; - Writer.Write(array.Count); - attr_type = Datamodel.GetArrayInnerType(array.GetType()); - foreach (var item in array) - WriteAttribute(item, true); - } + /// + /// Writes the type id of a value followed by the value itself, or by the item count and items for arrays. + /// + void WriteTypedValue(object? value, bool raw_string) + { + var attr_type = value == null ? typeof(Element) : value.GetType(); + var attr_type_id = TypeToId(attr_type, EncodingVersion); + Writer.Write(attr_type_id); + + if (value == null || !Datamodel.IsDatamodelArrayType(attr_type)) + { + WriteAttribute(value, raw_string); + return; } + + var array = (System.Collections.IList)value; + Writer.Write(array.Count); + foreach (var item in array) + WriteAttribute(item, true); } + /// Whether the value is an array item or a prefix attribute, in which case strings are written inline rather than through the dictionary. void WriteAttribute(object? value, bool in_array) { if (value == null) diff --git a/Datamodel.NET/Datamodel.ElementList.cs b/Datamodel.NET/Datamodel.ElementList.cs index 97fd548..ee612e2 100644 --- a/Datamodel.NET/Datamodel.ElementList.cs +++ b/Datamodel.NET/Datamodel.ElementList.cs @@ -203,6 +203,30 @@ public bool Remove(Element item, RemoveMode mode) finally { ChangeLock.ExitUpgradeableReadLock(); } } + /// + /// Removes an which the caller knows is not referenced by any other Element, without scanning the Datamodel. + /// + internal void RemoveUnreferenced(Element item) + { + ChangeLock.EnterWriteLock(); + try + { + if (!store.Contains(item.ID)) + { + return; + } + + store.Remove(item.ID); + item.Owner = null; + } + finally + { + ChangeLock.ExitWriteLock(); + } + + CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item)); + } + /// /// Removes unreferenced Elements from the Datamodel. /// diff --git a/Datamodel.NET/Datamodel.cs b/Datamodel.NET/Datamodel.cs index b23d53e..542e6db 100644 --- a/Datamodel.NET/Datamodel.cs +++ b/Datamodel.NET/Datamodel.cs @@ -575,6 +575,12 @@ public AttributeList PrefixAttributes get; protected set; } + /// + /// Gets or sets the ID under which are stored when the encoding also writes them as an element, + /// as "keyvalues2" and "binary" version 9 do. Preserved across a load and save cycle. + /// + public Guid PrefixElementId { get; set; } = Guid.NewGuid(); + /// /// Gets all Elements owned by this Datamodel. Only Elements which are referenced by the Root element or one of its children are actually considered part of the Datamodel. /// From f4f987841a988ab8ed2a50c0dff9c7b9eb09aaf2 Mon Sep 17 00:00:00 2001 From: Angel Date: Fri, 4 Sep 2026 11:53:39 +0200 Subject: [PATCH 05/13] Write byte[] as the binary type in encoding version 9 --- Datamodel.NET/Codecs/Binary.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Datamodel.NET/Codecs/Binary.cs b/Datamodel.NET/Codecs/Binary.cs index 7b3a6ab..4270cfd 100644 --- a/Datamodel.NET/Codecs/Binary.cs +++ b/Datamodel.NET/Codecs/Binary.cs @@ -53,7 +53,8 @@ static Binary() static byte TypeToId(Type type, int version) { - bool array = Datamodel.IsDatamodelArrayType(type); + // a byte[] is a "binary" blob, distinct from a "uint8_array" (Array) in encoding version 9 + bool array = type != typeof(byte[]) && Datamodel.IsDatamodelArrayType(type); var search_type = array ? Datamodel.GetArrayInnerType(type) : type; if (array && search_type == typeof(byte) && !SupportedAttributes[version].Contains(typeof(byte))) @@ -758,7 +759,7 @@ void WriteTypedValue(object? value, bool raw_string) var attr_type_id = TypeToId(attr_type, EncodingVersion); Writer.Write(attr_type_id); - if (value == null || !Datamodel.IsDatamodelArrayType(attr_type)) + if (value == null || value is byte[] || !Datamodel.IsDatamodelArrayType(attr_type)) { WriteAttribute(value, raw_string); return; From 44f982a7d3aa7152d28a4c23b3f38dedc39dbe51 Mon Sep 17 00:00:00 2001 From: Angel Date: Fri, 4 Sep 2026 11:54:07 +0200 Subject: [PATCH 06/13] Preserve null element references and array order in keyvalues2 --- Datamodel.NET/Codecs/KeyValues2.cs | 40 ++++++++++++++++-------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/Datamodel.NET/Codecs/KeyValues2.cs b/Datamodel.NET/Codecs/KeyValues2.cs index fb01f37..c0817ea 100644 --- a/Datamodel.NET/Codecs/KeyValues2.cs +++ b/Datamodel.NET/Codecs/KeyValues2.cs @@ -361,7 +361,7 @@ public void Encode(Datamodel dm, string encoding, int encodingVersion, Stream st writer.WriteTokens("$prefix_element$"); writer.WriteLine("{"); writer.Indent++; - writer.WriteTokenLine("id", "elementid", Guid.NewGuid().ToString()); + writer.WriteTokenLine("id", "elementid", dm.PrefixElementId.ToString()); foreach (var attr in dm.PrefixAttributes) if (attr.Value != null) { @@ -405,7 +405,9 @@ private class IntermediateData // we can go trough these and actually create the attributes // and add the elements to lists public Dictionary> PropertiesToAdd = []; - public Dictionary> ListRefs = []; + + // array items referenced by id keep their slot (filled with null while parsing) and are resolved in place afterwards + public List<(IList List, int Index, Guid Id)> ListRefs = []; public void HandleElementProp(Element? element, string attrName, Guid id) { @@ -426,17 +428,10 @@ public void HandleElementProp(Element? element, string attrName, Guid id) } - public void HandleListRefs(IList list, Guid id) + public void HandleListRefs(ElementArray list, Guid id) { - ListRefs.TryGetValue(list, out var guidList); - - if (guidList == null) - { - guidList = []; - ListRefs.Add(list, guidList); - } - - guidList.Add(id); + list.Add(null!); + ListRefs.Add((list, list.Count - 1, id)); } } @@ -511,6 +506,10 @@ string Decode_NextToken(StreamReader reader) CodecUtilities.TryConstructCustomElement(elementFactory, reflectionParams, dataModel, elem_class, elem_name, id, out elem); elem ??= new Element(dataModel, elem_name, id, elem_class); } + else + { + dataModel.PrefixElementId = id; + } continue; } @@ -527,6 +526,9 @@ string Decode_NextToken(StreamReader reader) { var id_s = Decode_NextToken(reader); + // the attribute keeps its position, it is filled in once every element has been parsed; an empty id is a null reference + elem?.Add(attr_name, null); + if (!string.IsNullOrEmpty(id_s)) { intermediateData.HandleElementProp(elem, attr_name, new Guid(id_s)); @@ -556,7 +558,11 @@ string Decode_NextToken(StreamReader reader) if (!string.IsNullOrEmpty(id_s)) { - intermediateData.HandleListRefs(array, new Guid(id_s)); + intermediateData.HandleListRefs((ElementArray)array, new Guid(id_s)); + } + else + { + ((ElementArray)array).Add(null!); } } // inline Element @@ -698,13 +704,9 @@ public Datamodel Decode(string encoding, int encoding_version, string format, in } - foreach (var list in intermediateData.ListRefs) + foreach (var (list, index, id) in intermediateData.ListRefs) { - foreach (var id in list.Value) - { - var elemToAdd = dataModel.AllElements[id]; - list.Key.Add(elemToAdd); - } + list[index] = dataModel.AllElements[id]; } return dataModel; From e9ba30075aaefb31e83a9644f6f439a62acff053 Mon Sep 17 00:00:00 2001 From: Angel Date: Fri, 4 Sep 2026 11:56:21 +0200 Subject: [PATCH 07/13] Escape control characters in keyvalues2 strings --- Datamodel.NET/Codecs/KeyValues2.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/Datamodel.NET/Codecs/KeyValues2.cs b/Datamodel.NET/Codecs/KeyValues2.cs index c0817ea..87e072a 100644 --- a/Datamodel.NET/Codecs/KeyValues2.cs +++ b/Datamodel.NET/Codecs/KeyValues2.cs @@ -78,7 +78,12 @@ public void Dispose() static string Sanitise(string value) { - return value.Replace("\"", "\\\""); + return value + .Replace("\\", "\\\\") + .Replace("\"", "\\\"") + .Replace("\n", "\\n") + .Replace("\r", "\\r") + .Replace("\t", "\\t"); } /// @@ -449,7 +454,13 @@ string Decode_NextToken(StreamReader reader) var c = (char)read; if (escaped) { - TokenBuilder.Append(c); + TokenBuilder.Append(c switch + { + 'n' => '\n', + 'r' => '\r', + 't' => '\t', + _ => c, + }); escaped = false; continue; } @@ -464,6 +475,7 @@ string Decode_NextToken(StreamReader reader) case '\r': case '\n': Line++; + if (in_block) TokenBuilder.Append(c); break; case '{': case '}': From d12958e754a3b48a73e0dd39d160b6c5da2514b4 Mon Sep 17 00:00:00 2001 From: Angel Date: Fri, 4 Sep 2026 11:56:22 +0200 Subject: [PATCH 08/13] Lay out keyvalues2 text like Valve's serializer --- Datamodel.NET/Codecs/KeyValues2.cs | 316 ++++++++++++----------------- 1 file changed, 125 insertions(+), 191 deletions(-) diff --git a/Datamodel.NET/Codecs/KeyValues2.cs b/Datamodel.NET/Codecs/KeyValues2.cs index 87e072a..24e14fa 100644 --- a/Datamodel.NET/Codecs/KeyValues2.cs +++ b/Datamodel.NET/Codecs/KeyValues2.cs @@ -49,26 +49,18 @@ static KeyValues2() } #region Encode + /// + /// Writes lines with tab indentation and LF line endings, as the reference serializer does. + /// class KV2Writer : IDisposable { - public int Indent - { - get { return indent_count; } - set - { - indent_count = value; - indent_string = Context.GetIndentation(value); - } - } - int indent_count = 0; - string indent_string = "\n"; + public int Indent { get; set; } + readonly TextWriter Output; - readonly SerializationContext Context; - public KV2Writer(Stream output, SerializationContext context) + public KV2Writer(Stream output) { Output = new StreamWriter(output, Datamodel.TextEncoding); - Context = context; } public void Dispose() @@ -76,7 +68,7 @@ public void Dispose() Output.Dispose(); } - static string Sanitise(string value) + public static string Sanitise(string value) { return value .Replace("\\", "\\\\") @@ -86,47 +78,20 @@ static string Sanitise(string value) .Replace("\t", "\\t"); } - /// - /// Writes the string straight to the output steam, with no sanitisation. - /// - public void Write(string value) - { - Output.Write(value); - } + public static string Token(string value) => "\"" + Sanitise(value) + "\""; - public void WriteTokens(params string[] values) + public void WriteLine(string line) { - Output.Write('"' + string.Join("\" \"", values.Select(s => Sanitise(s))) + '"'); - } - - public void WriteLine() - { - Output.Write(indent_string); - } + for (var i = 0; i < Indent; i++) + Output.Write('\t'); - /// - /// Writes a new line followed by the given value - /// - public void WriteLine(string value) - { - WriteLine(); - Output.Write(value); + Output.Write(line); + Output.Write('\n'); } - public void WriteTokenLine(params string[] values) - { - Output.Write(indent_string); - WriteTokens(values); - } - - public void TrimEnd(int count) + public void WriteLine() { - if (count > 0) - { - Output.Flush(); - var stream = ((StreamWriter)Output).BaseStream; - stream.SetLength(stream.Length - count); - } + Output.Write('\n'); } public void Flush() @@ -135,8 +100,8 @@ public void Flush() } } - // Multi-referenced elements are written out as a separate block at the end of the file. - // In-line only the id is written. + // Elements referenced more than once are written as separate blocks after the root and referred to by id. + // Elements referenced once are written inline. Dictionary ReferenceCount = []; SerializationContext Context = new(); @@ -172,209 +137,178 @@ void CountReferences(Element? elem) } } - void WriteAttribute(string name, int encodingVersion, Type type, object value, bool in_array, KV2Writer writer) + static string FormatFloat(float value) { - bool is_element = type == typeof(Element) || type.IsSubclassOf(typeof(Element)); + // ten decimals with trailing zeros dropped, as the reference serializer prints them + return ((double)value).ToString("0.##########", CultureInfo.InvariantCulture); + } - Type? inner_type = null; - if (!in_array) - { - // TODO: subclass check in this method like above - and in all other places with == typeof(Element) - inner_type = Datamodel.GetArrayInnerType(type); + static string FormatFloats(params float[] values) + { + return string.Join(" ", values.Select(FormatFloat)); + } + + static string FormatValue(object value) + { + return value switch + { + string stringValue => stringValue, + bool boolValue => boolValue ? "1" : "0", + int intValue => intValue.ToString(CultureInfo.InvariantCulture), + float floatValue => FormatFloat(floatValue), + byte byteValue => byteValue.ToString(CultureInfo.InvariantCulture), + ulong ulongValue => "0x" + ulongValue.ToString("x", CultureInfo.InvariantCulture), + byte[] binaryValue => Convert.ToHexString(binaryValue), + TimeSpan timeValue => FormatFloat((float)timeValue.TotalSeconds), + Color colorValue => FormattableString.Invariant($"{colorValue.R} {colorValue.G} {colorValue.B} {colorValue.A}"), + Vector2 v => FormatFloats(v.X, v.Y), + Vector3 v => FormatFloats(v.X, v.Y, v.Z), + Vector4 v => FormatFloats(v.X, v.Y, v.Z, v.W), + Quaternion q => FormatFloats(q.X, q.Y, q.Z, q.W), + QAngle a => FormatFloats(a.Pitch, a.Yaw, a.Roll), + Matrix4x4 m => FormatFloats(m.M11, m.M12, m.M13, m.M14, m.M21, m.M22, m.M23, m.M24, m.M31, m.M32, m.M33, m.M34, m.M41, m.M42, m.M43, m.M44), + _ => throw new CodecException($"Cannot serialize a value of type {value.GetType().Name} to KeyValues2"), + }; + } - if (inner_type == typeof(byte) && type == typeof(byte[])) - inner_type = null; // serialize as binary at all times + void WriteAttribute(string name, int encodingVersion, object? value, KV2Writer writer) + { + var nameToken = KV2Writer.Token(name); - /* - if (inner_type == typeof(byte) && !ValidAttributes[EncodingVersion].Contains(typeof(byte))) - inner_type = null; // fall back on the "binary" type in older KV2 versions - */ + if (value is null || value is Element) + { + WriteElementAttribute(nameToken, encodingVersion, (Element?)value, writer); + return; } - // Elements are supported by all. - if (!is_element && !ValidAttributes[encodingVersion].Contains(inner_type ?? type)) - throw new CodecException(type.Name + " is not valid in KeyValues2 " + encodingVersion); + var type = value.GetType(); - if (inner_type != null) - { - is_element = inner_type == typeof(Element); + // a byte[] is always serialized as "binary", never as a uint8_array + var innerType = type == typeof(byte[]) ? null : Datamodel.GetArrayInnerType(type); - writer.WriteTokenLine(name, TypeNames[inner_type] + "_array"); + if (innerType != null) + { + if (!ValidAttributes[encodingVersion].Contains(innerType)) + throw new CodecException(innerType.Name + " is not valid in KeyValues2 " + encodingVersion); - if (((System.Collections.IList)value).Count == 0) - { - writer.Write(" [ ]"); - return; - } + WriteArrayAttribute(nameToken, encodingVersion, innerType, (IList)value, writer); + return; + } - if (is_element) writer.WriteLine("["); - else writer.Write(" ["); + if (!ValidAttributes[encodingVersion].Contains(type)) + throw new CodecException(type.Name + " is not valid in KeyValues2 " + encodingVersion); - writer.Indent++; - foreach (var array_value in (System.Collections.IList)value) - WriteAttribute(string.Empty, encodingVersion, inner_type, array_value, true, writer); - writer.Indent--; - writer.TrimEnd(1); // remove trailing comma + writer.WriteLine($"{nameToken} {KV2Writer.Token(TypeNames[type])} {KV2Writer.Token(FormatValue(value))}"); + } - if (inner_type == typeof(Element)) writer.WriteLine("]"); - else writer.Write(" ]"); + void WriteElementAttribute(string nameToken, int encodingVersion, Element? elem, KV2Writer writer) + { + if (elem is null || ShouldBeReferenced(elem)) + { + writer.WriteLine($"{nameToken} \"element\" \"{(elem is null ? string.Empty : elem.ID.ToString())}\""); return; } - if (is_element) + writer.WriteLine($"{nameToken} {KV2Writer.Token(elem.ClassName)}"); + WriteElementBody(elem, encodingVersion, writer); + writer.WriteLine("}"); + + // the reference serializer leaves a blank line after an inline element + writer.WriteLine(); + } + + void WriteArrayAttribute(string nameToken, int encodingVersion, Type innerType, IList array, KV2Writer writer) + { + writer.WriteLine($"{nameToken} {KV2Writer.Token(TypeNames[innerType] + "_array")} "); + writer.WriteLine("["); + writer.Indent++; + + for (var i = 0; i < array.Count; i++) { - var elem = (Element)value; - var id = elem.ID.ToString(); + var separator = i == array.Count - 1 ? string.Empty : ","; + var item = array[i]; - if (in_array) + if (innerType == typeof(Element)) { - if (ShouldBeReferenced(elem)) + var elem = (Element?)item; + + if (elem is null || ShouldBeReferenced(elem)) { - writer.WriteTokenLine("element", id); + writer.WriteLine($"\"element\" \"{(elem is null ? string.Empty : elem.ID.ToString())}\"{separator}"); } else { - writer.WriteLine(); - WriteElement(elem, encodingVersion, writer); + writer.WriteLine(KV2Writer.Token(elem.ClassName)); + WriteElementBody(elem, encodingVersion, writer); + writer.WriteLine("}" + separator); } - - writer.Write(","); } else { - if (ShouldBeReferenced(elem)) - { - writer.WriteTokenLine(name, "element", id); - } - else - { - writer.WriteLine($"\"{name}\" "); - WriteElement(elem, encodingVersion, writer); - } + writer.WriteLine(KV2Writer.Token(FormatValue(item!)) + separator); } } - else - { - if (type == typeof(bool)) - value = (bool)value ? 1 : 0; - else if (type == typeof(float)) - value = FormattableString.Invariant($"{(float)value}"); - else if (type == typeof(byte[])) - value = Convert.ToHexString((byte[])value).Replace("-", string.Empty, false, CultureInfo.InvariantCulture); - else if (type == typeof(TimeSpan)) - value = ((TimeSpan)value).TotalSeconds.ToString(CultureInfo.InvariantCulture); - else if (type == typeof(Color)) - { - var castValue = (Color)value; - value = FormattableString.Invariant($"{castValue.R} {castValue.G} {castValue.B} {castValue.A}"); - } - else if (value is ulong ulong_value) - value = $"0x{ulong_value.ToString("x", CultureInfo.InvariantCulture)}"; - else if (type == typeof(Vector2)) - { - var castValue = (Vector2)value; - value = FormattableString.Invariant($"{castValue.X} {castValue.Y}"); - } - else if (type == typeof(Vector3)) - { - var castValue = (Vector3)value; - value = FormattableString.Invariant($"{castValue.X} {castValue.Y} {castValue.Z}"); - } - else if (type == typeof(Vector4)) - { - var castValue = (Vector4)value; - value = FormattableString.Invariant($"{castValue.X} {castValue.Y} {castValue.Z} {castValue.W}"); - } - else if (type == typeof(Quaternion)) - { - var castValue = (Quaternion)value; - value = FormattableString.Invariant($"{castValue.X} {castValue.Y} {castValue.Z} {castValue.W}"); - } - else if (type == typeof(Matrix4x4)) - { - var castValue = (Matrix4x4)value; - value = - FormattableString.Invariant($"{castValue.M11} {castValue.M12} {castValue.M13} {castValue.M14}") + - FormattableString.Invariant($" {castValue.M21} {castValue.M22} {castValue.M23} {castValue.M24}") + - FormattableString.Invariant($" {castValue.M31} {castValue.M32} {castValue.M33} {castValue.M34}") + - FormattableString.Invariant($" {castValue.M41} {castValue.M42} {castValue.M43} {castValue.M44}"); - } - else if (value is QAngle castValue) - { - value = FormattableString.Invariant($"{castValue.Pitch} {castValue.Yaw} {castValue.Roll}"); - } - - if (in_array) - writer.Write(FormattableString.Invariant($" \"{value}\",")); - else - writer.WriteTokenLine(name, TypeNames[type], FormattableString.Invariant($"{value}")); - } + writer.Indent--; + writer.WriteLine("]"); } - private bool ShouldBeReferenced(Element? elem) + private bool ShouldBeReferenced(Element elem) { - if (elem is null) - { - return false; - } - - return SupportsReferenceIds && (elem == null || ReferenceCount.TryGetValue(elem, out var refCount) && refCount > 1); + return SupportsReferenceIds && ReferenceCount.TryGetValue(elem, out var refCount) && refCount > 1; } - void WriteElement(Element element, int encodingVersion, KV2Writer writer) + /// + /// Writes the opening brace, id, name and attributes of an element. The caller writes the class name before and the closing brace after. + /// + void WriteElementBody(Element element, int encodingVersion, KV2Writer writer) { if (TypeNames.ContainsValue(element.ClassName)) throw new CodecException($"Element {element.ID} uses reserved type name \"{element.ClassName}\""); - writer.WriteTokens(element.ClassName); + writer.WriteLine("{"); writer.Indent++; if (SupportsReferenceIds) - writer.WriteTokenLine("id", "elementid", element.ID.ToString()); + writer.WriteLine($"\"id\" \"elementid\" \"{element.ID}\""); - // Skip empty names right now. if (!string.IsNullOrEmpty(element.Name)) - { - writer.WriteTokenLine("name", "string", element.Name); - } + writer.WriteLine($"\"name\" \"string\" {KV2Writer.Token(element.Name)}"); foreach (var attr in Context.Attributes[element]) - { - if (attr.Value != null) - WriteAttribute(attr.Key, encodingVersion, attr.Value.GetType(), attr.Value, false, writer); - } + WriteAttribute(attr.Key, encodingVersion, attr.Value, writer); writer.Indent--; + } + + void WriteElement(Element element, int encodingVersion, KV2Writer writer) + { + writer.WriteLine(KV2Writer.Token(element.ClassName)); + WriteElementBody(element, encodingVersion, writer); writer.WriteLine("}"); } public void Encode(Datamodel dm, string encoding, int encodingVersion, Stream stream) { Context = new SerializationContext(); - var writer = new KV2Writer(stream, Context); + var writer = new KV2Writer(stream); SupportsReferenceIds = encoding != "keyvalues2_noids"; - writer.Write(String.Format(CodecUtilities.HeaderPattern, encoding, encodingVersion, dm.Format, dm.FormatVersion)); - writer.WriteLine(); + writer.WriteLine(string.Format(CodecUtilities.HeaderPattern, encoding, encodingVersion, dm.Format, dm.FormatVersion)); ReferenceCount = []; if (encodingVersion >= 4 && dm.PrefixAttributes.Count > 0) { - writer.WriteTokens("$prefix_element$"); + writer.WriteLine("\"$prefix_element$\""); writer.WriteLine("{"); writer.Indent++; - writer.WriteTokenLine("id", "elementid", dm.PrefixElementId.ToString()); + writer.WriteLine($"\"id\" \"elementid\" \"{dm.PrefixElementId}\""); foreach (var attr in dm.PrefixAttributes) - if (attr.Value != null) - { - WriteAttribute(attr.Key, encodingVersion, attr.Value.GetType(), attr.Value, false, writer); - } + WriteAttribute(attr.Key, encodingVersion, attr.Value, writer); writer.Indent--; writer.WriteLine("}"); - writer.WriteLine(); } if (SupportsReferenceIds) @@ -383,8 +317,8 @@ public void Encode(Datamodel dm, string encoding, int encodingVersion, Stream st if (dm.Root != null) { WriteElement(dm.Root, encodingVersion, writer); + writer.WriteLine(); } - writer.WriteLine(); if (SupportsReferenceIds) { @@ -392,7 +326,7 @@ public void Encode(Datamodel dm, string encoding, int encodingVersion, Stream st { if (pair.Key == dm.Root) continue; - writer.WriteLine(); + WriteElement(pair.Key, encodingVersion, writer); writer.WriteLine(); } From 69d522c5489bb9475ae9abf171ed4dd793920d7b Mon Sep 17 00:00:00 2001 From: Angel Date: Fri, 4 Sep 2026 11:56:22 +0200 Subject: [PATCH 09/13] Generate an internal, auto-generated ElementFactory --- ElementFactoryGenerator/ElementFactory.cs | 7 ++++++- ElementFactoryGenerator/ElementFactoryGenerator.csproj | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ElementFactoryGenerator/ElementFactory.cs b/ElementFactoryGenerator/ElementFactory.cs index 8abe6c8..bd4383d 100644 --- a/ElementFactoryGenerator/ElementFactory.cs +++ b/ElementFactoryGenerator/ElementFactory.cs @@ -39,11 +39,16 @@ private void Execute(SourceProductionContext context, (Compilation Left, Immutab var assemblies = new List(); + // marked as generated so that analyzers and documentation warnings of the consuming project leave it alone, + // and internal so that it does not become part of the consuming assembly's public surface elementFactory.Append( """" + // #nullable enable + #pragma warning disable - public class ElementFactory : Datamodel.Codecs.IElementFactory + [global::System.CodeDom.Compiler.GeneratedCode("KeyValues2.ElementFactoryGenerator", "0.2.1")] + internal sealed class ElementFactory : Datamodel.Codecs.IElementFactory { public object? GetClass(string assembly, string nameSpace, string classname) { diff --git a/ElementFactoryGenerator/ElementFactoryGenerator.csproj b/ElementFactoryGenerator/ElementFactoryGenerator.csproj index 127b336..36250a2 100644 --- a/ElementFactoryGenerator/ElementFactoryGenerator.csproj +++ b/ElementFactoryGenerator/ElementFactoryGenerator.csproj @@ -3,7 +3,7 @@ netstandard2.0 latest - 0.2 + 0.2.1 enable true snupkg From 49defe44783f70dc1df66b590da6192e6d2cc60d Mon Sep 17 00:00:00 2001 From: Angel Date: Fri, 4 Sep 2026 11:56:22 +0200 Subject: [PATCH 10/13] Consult every generated element factory when loading typed elements --- Datamodel.NET/Codecs/Binary.cs | 5 +- Datamodel.NET/Codecs/KeyValues2.cs | 21 +++---- Datamodel.NET/Datamodel.NET.csproj | 4 +- Datamodel.NET/Datamodel.cs | 1 + Datamodel.NET/ICodec.cs | 97 +++++++++++++++++++++++++++--- 5 files changed, 105 insertions(+), 23 deletions(-) diff --git a/Datamodel.NET/Codecs/Binary.cs b/Datamodel.NET/Codecs/Binary.cs index 4270cfd..458123b 100644 --- a/Datamodel.NET/Codecs/Binary.cs +++ b/Datamodel.NET/Codecs/Binary.cs @@ -397,8 +397,7 @@ private static Matrix4x4 ReadMatrix4x4(BinaryReader reader) public Datamodel Decode(string encoding, int encoding_version, string format, int format_version, Stream stream, DeferredMode defer_mode, ReflectionParams reflectionParams) { - var elementFactoryTypes = CodecUtilities.GetIElementFactoryClasses(); - var elementFactory = (IElementFactory)Activator.CreateInstance(elementFactoryTypes.First()); + var resolver = new ElementTypeResolver(reflectionParams); stream.Seek(0, SeekOrigin.Begin); while (true) @@ -438,7 +437,7 @@ public Datamodel Decode(string encoding, int encoding_version, string format, in var id_bits = Reader.ReadBytes(16); var id = new Guid(BitConverter.IsLittleEndian ? id_bits : id_bits.Reverse().ToArray()); - if (!CodecUtilities.TryConstructCustomElement(elementFactory, reflectionParams, dm, type, name, id, out var elem)) + if (!CodecUtilities.TryConstructCustomElement(resolver, dm, type, name, id, out var elem)) { // note: constructing an element, adds it to the datamodel.AllElements elem = new Element(dm, name, id, type); diff --git a/Datamodel.NET/Codecs/KeyValues2.cs b/Datamodel.NET/Codecs/KeyValues2.cs index 24e14fa..96eae02 100644 --- a/Datamodel.NET/Codecs/KeyValues2.cs +++ b/Datamodel.NET/Codecs/KeyValues2.cs @@ -425,7 +425,7 @@ string Decode_NextToken(StreamReader reader) } } - Element? Decode_ParseElement(IElementFactory elementFactory, string class_name, ReflectionParams reflectionParams, StreamReader reader, Datamodel dataModel, IntermediateData intermediateData) + Element? Decode_ParseElement(ElementTypeResolver resolver, string class_name, StreamReader reader, Datamodel dataModel, IntermediateData intermediateData) { string elem_class = class_name ?? Decode_NextToken(reader); string elem_name = string.Empty; @@ -449,7 +449,7 @@ string Decode_NextToken(StreamReader reader) var id = new Guid(elem_id); if (elem_class != "$prefix_element$") { - CodecUtilities.TryConstructCustomElement(elementFactory, reflectionParams, dataModel, elem_class, elem_name, id, out elem); + CodecUtilities.TryConstructCustomElement(resolver, dataModel, elem_class, elem_name, id, out elem); elem ??= new Element(dataModel, elem_name, id, elem_class); } else @@ -485,7 +485,7 @@ string Decode_NextToken(StreamReader reader) object? attr_value = null; if (attr_type == null) - attr_value = Decode_ParseElement(elementFactory, attr_type_s, reflectionParams, reader, dataModel, intermediateData); + attr_value = Decode_ParseElement(resolver, attr_type_s, reader, dataModel, intermediateData); else if (attr_type_s.EndsWith("_array")) { var array = CodecUtilities.MakeList(attr_type, 5); // assume 5 items @@ -514,17 +514,17 @@ string Decode_NextToken(StreamReader reader) // inline Element else if (attr_type == typeof(Element)) { - array.Add(Decode_ParseElement(elementFactory, next, reflectionParams, reader, dataModel, intermediateData)); + array.Add(Decode_ParseElement(resolver, next, reader, dataModel, intermediateData)); } // normal value else { - array.Add(Decode_ParseValue(elementFactory, attr_type, next, reflectionParams, reader, dataModel, intermediateData)); + array.Add(Decode_ParseValue(resolver, attr_type, next, reader, dataModel, intermediateData)); } } } else - attr_value = Decode_ParseValue(elementFactory, attr_type, Decode_NextToken(reader), reflectionParams, reader, dataModel, intermediateData); + attr_value = Decode_ParseValue(resolver, attr_type, Decode_NextToken(reader), reader, dataModel, intermediateData); if (elem != null) elem.Add(attr_name, attr_value); @@ -534,7 +534,7 @@ string Decode_NextToken(StreamReader reader) return elem; } - object? Decode_ParseValue(IElementFactory elementFactory, Type type, string value, ReflectionParams reflectionParams, StreamReader reader, Datamodel dataModel, IntermediateData intermediateData) + object? Decode_ParseValue(ElementTypeResolver resolver, Type type, string value, StreamReader reader, Datamodel dataModel, IntermediateData intermediateData) { if (type == typeof(string)) return value; @@ -542,7 +542,7 @@ string Decode_NextToken(StreamReader reader) value = value.Trim(); if (type == typeof(Element)) - return Decode_ParseElement(elementFactory, value, reflectionParams, reader, dataModel, intermediateData); + return Decode_ParseElement(resolver, value, reader, dataModel, intermediateData); if (type == typeof(int)) return int.Parse(value, CultureInfo.InvariantCulture); else if (type == typeof(float)) @@ -612,8 +612,7 @@ string Decode_NextToken(StreamReader reader) public Datamodel Decode(string encoding, int encoding_version, string format, int format_version, Stream stream, DeferredMode defer_mode, ReflectionParams reflectionParams) { - var elementFactoryTypes = CodecUtilities.GetIElementFactoryClasses(); - var elementFactory = (IElementFactory)Activator.CreateInstance(elementFactoryTypes.First()); + var resolver = new ElementTypeResolver(reflectionParams); var dataModel = new Datamodel(format, format_version); @@ -636,7 +635,7 @@ public Datamodel Decode(string encoding, int encoding_version, string format, in { break; } try - { Decode_ParseElement(elementFactory, next, reflectionParams, reader, dataModel, intermediateData); } + { Decode_ParseElement(resolver, next, reader, dataModel, intermediateData); } catch (Exception err) { throw new CodecException($"KeyValues2 decode failed on line {Line}:\n\n{err.Message}", err); } } diff --git a/Datamodel.NET/Datamodel.NET.csproj b/Datamodel.NET/Datamodel.NET.csproj index d91195a..3414567 100644 --- a/Datamodel.NET/Datamodel.NET.csproj +++ b/Datamodel.NET/Datamodel.NET.csproj @@ -57,7 +57,7 @@ - + - + diff --git a/Datamodel.NET/Datamodel.cs b/Datamodel.NET/Datamodel.cs index 542e6db..4e993b7 100644 --- a/Datamodel.NET/Datamodel.cs +++ b/Datamodel.NET/Datamodel.cs @@ -335,6 +335,7 @@ private static Datamodel Load_Internal(Stream stream, DeferredMode defer_mode reflectionParams.Namespace = templateType.Namespace!; } + reflectionParams.RootAssembly ??= templateType.Assembly; stream.Seek(0, SeekOrigin.Begin); var header = string.Empty; diff --git a/Datamodel.NET/ICodec.cs b/Datamodel.NET/ICodec.cs index aeee3f2..3ca6260 100644 --- a/Datamodel.NET/ICodec.cs +++ b/Datamodel.NET/ICodec.cs @@ -49,6 +49,77 @@ public class ReflectionParams(bool attemptReflection = true, List? additio public string Assembly = string.Empty; public string Namespace = string.Empty; + + /// + /// Assembly of the root type passed to Load. Its generated is asked first. + /// + public Assembly? RootAssembly; + } + + /// + /// Resolves element class names to subclasses while decoding, through the + /// classes the ElementFactoryGenerator emits into every assembly that references this library. + /// + /// + /// Every factory in the process is consulted, the one generated into the root type's own assembly first. Each factory only knows + /// the assemblies its compilation referenced, and this library's own factory knows nothing, so stopping at the first one found + /// would depend on assembly load order. + /// + public sealed class ElementTypeResolver + { + private const string GeneratedFactoryTypeName = "ElementFactory"; + + private readonly ReflectionParams reflectionParams; + private readonly List factories = []; + + public ElementTypeResolver(ReflectionParams reflectionParams) + { + this.reflectionParams = reflectionParams; + + if (!reflectionParams.AttemptReflection) + { + return; + } + + var factoryTypes = new List(); + + if (reflectionParams.RootAssembly?.GetType(GeneratedFactoryTypeName) is Type rootFactory) + { + factoryTypes.Add(rootFactory); + } + + foreach (var factoryType in CodecUtilities.GetIElementFactoryClasses()) + { + if (!factoryTypes.Contains(factoryType)) + { + factoryTypes.Add(factoryType); + } + } + + foreach (var factoryType in factoryTypes) + { + if (Activator.CreateInstance(factoryType) is IElementFactory factory) + { + factories.Add(factory); + } + } + } + + /// + /// Constructs a new, unowned instance of the class registered for the given element class name, or null when no factory knows it. + /// + public Element? Construct(string className) + { + foreach (var factory in factories) + { + if (factory.GetClass(reflectionParams.Assembly, reflectionParams.Namespace, className) is Element element) + { + return element; + } + } + + return null; + } } @@ -191,9 +262,13 @@ public static void AddDeferredAttribute(Element elem, string key, long offset) elem.Add(key, offset); } - public static bool TryConstructCustomElement(IElementFactory elementFactory, ReflectionParams reflectionParams, Datamodel dataModel, string elem_class, string elem_name, Guid elem_id, out Element? elem) + /// + /// Constructs an element of the subclass registered for and adds it to the Datamodel. + /// + /// False when no subclass is registered for the class name, in which case a plain should be used. + public static bool TryConstructCustomElement(ElementTypeResolver resolver, Datamodel dataModel, string elem_class, string elem_name, Guid elem_id, out Element? elem) { - elem = (Element?)elementFactory.GetClass(reflectionParams.Assembly, reflectionParams.Namespace, elem_class); + elem = resolver.Construct(elem_class); if (elem is null) { @@ -201,16 +276,21 @@ public static bool TryConstructCustomElement(IElementFactory elementFactory, Ref } elem.ID = elem_id; - elem.Owner = dataModel; elem.Name = elem_name; elem.ClassName = elem_class; + elem.Owner = dataModel; return true; } - public static IEnumerable GetIElementFactoryClasses() + private static Type[]? elementFactoryClasses; + + /// + /// Finds every implementation in the loaded assemblies. The result is cached after the first call. + /// + public static IEnumerable GetIElementFactoryClasses() { - return AppDomain.CurrentDomain.GetAssemblies() + elementFactoryClasses ??= AppDomain.CurrentDomain.GetAssemblies() .SelectMany(assembly => { try @@ -219,12 +299,15 @@ public static bool TryConstructCustomElement(IElementFactory elementFactory, Ref } catch (ReflectionTypeLoadException ex) { - return ex.Types.Where(t => t != null); + return ex.Types.OfType(); } }) .Where(type => type.IsClass && !type.IsAbstract && - type.GetInterfaces().Contains(typeof(IElementFactory))); + type.GetInterfaces().Contains(typeof(IElementFactory))) + .ToArray(); + + return elementFactoryClasses; } } From 66ef2742f50defa666eee8fbff465a1239bb22ed Mon Sep 17 00:00:00 2001 From: Angel Date: Fri, 4 Sep 2026 11:56:22 +0200 Subject: [PATCH 11/13] Update the test vmap schema to match ValveResourceFormat --- Tests/Tests.cs | 34 +- Tests/ValveMap.cs | 2011 +++++++++++++++++++++++++++++++++++++++------ 2 files changed, 1782 insertions(+), 263 deletions(-) diff --git a/Tests/Tests.cs b/Tests/Tests.cs index 7dd127d..599a671 100644 --- a/Tests/Tests.cs +++ b/Tests/Tests.cs @@ -362,34 +362,29 @@ private static void Validate_Vmap_Reflection(Datamodel.Datamodel unserialisedVma CMapRootElement root = (CMapRootElement)unserialisedVmap.Root; - Assert.AreEqual(typeof(CMapWorld), root.world.GetType()); + Assert.AreEqual(typeof(CMapWorld), root.World.GetType()); - var world = root.world; + var world = root.World; - var props = world.children.Where(i => i.ClassName == "CMapEntity").OfType().ToList(); + var props = world.GetChildren().ToList(); + Assert.That(props, Is.Not.Empty); + Assert.That(props[0].GetEntityClassName(), Is.Not.Null); - var prop = props[0]; - var propclass = prop.ClassName; - var proptype = prop.GetType(); - var entityprop = prop; - - - var propProperties = props[0].EntityProperties; - var classname = propProperties.Get("classname"); - - var meshes = world.children.Where(i => i.ClassName == "CMapMesh").OfType().ToList(); + var meshes = world.GetChildren().ToList(); var mesh = meshes[0]; - var vertexData = mesh.meshData.vertexData; + var vertexData = mesh.MeshData.VertexData; - Assert.AreEqual(vertexData.size, 8); - Assert.AreEqual(vertexData.streams[0]["semanticName"], "position"); + Assert.AreEqual(vertexData.Size, 8); + Assert.AreEqual(vertexData.Streams[0]["semanticName"], "position"); - var typedPolygonMeshData = (CDmePolygonMeshDataStream)vertexData.streams[0]; - Assert.AreEqual(typedPolygonMeshData.semanticName, "position"); + var typedPolygonMeshData = (CDmePolygonMeshDataStream)vertexData.Streams[0]; + Assert.AreEqual(typedPolygonMeshData.SemanticName, "position"); - var typedPolygonMeshDataStream = typedPolygonMeshData.data as Vector3Array; + var typedPolygonMeshDataStream = typedPolygonMeshData.Data as Vector3Array; Assert.IsNotNull(typedPolygonMeshDataStream); + Assert.That(vertexData.GetStreamData("position"), Is.SameAs(typedPolygonMeshDataStream)); + Assert.That(mesh.MeshData.FaceVertexData.GetStreamData("normal"), Is.Not.Null); Assert.That(unserialisedVmap.PrefixAttributes["map_asset_references"], Is.Not.Empty); @@ -409,7 +404,6 @@ private static void Validate_Vmap_Reflection(Datamodel.Datamodel unserialisedVma Assert.That(elem, Is.Not.TypeOf(), $"Found object {elem.ID} {elem.ClassName} that is still an Element type."); } - } [Test] diff --git a/Tests/ValveMap.cs b/Tests/ValveMap.cs index 9037024..349e977 100644 --- a/Tests/ValveMap.cs +++ b/Tests/ValveMap.cs @@ -1,389 +1,1914 @@ -using Datamodel.Format; +using System; +using System.Collections; +using System.Collections.Generic; using System.Numerics; +using System.Diagnostics.CodeAnalysis; +using Datamodel.Format; using DMElement = Datamodel.Element; namespace Tests.VMAP; -#nullable enable +/// +/// Shared justification for helpers that must be methods: every public property of an element class is written to the file as an attribute. +/// +internal static class ValveMapSchema +{ + public const string SerializedPropertiesJustification = "Public properties of an element are serialized as attributes"; +} /// /// Valve Map (VMAP) format version 29. /// -internal class CMapRootElement : DMElement +/// +/// Every class in this file maps one to one onto an element class of the file format, so a map can be loaded +/// through the ValveMapFile class of ValveResourceFormat, inspected and edited through these properties, and written back. +/// Attributes of a file that no property claims are kept on the element and written back unchanged. +/// +[LowercaseProperties] +public class CMapRootElement : DMElement { - public bool isprefab { get; set; } - public int editorbuild { get; set; } = 8600; - public int editorversion { get; set; } = 400; - public bool showgrid { get; set; } = true; - public int snaprotationangle { get; set; } = 15; - public float gridspacing { get; set; } = 64; - public bool show3dgrid { get; set; } = true; + /// + /// Whether this file is a prefab rather than a standalone map. + /// + public bool IsPrefab { get; set; } + + /// + /// Hammer build number that wrote the file. + /// + public int EditorBuild { get; set; } = 8600; + + /// + /// Map format version. + /// + public int EditorVersion { get; set; } = 400; + + /// + /// Whether the 2D grid is drawn. + /// + public bool ShowGrid { get; set; } = true; + + /// + /// Rotation snap in degrees. + /// + public int SnapRotationAngle { get; set; } = 15; + + /// + /// Translation snap in world units. + /// + public float GridSpacing { get; set; } = 64; + + /// + /// Whether the 3D grid is drawn. + /// + public bool Show3DGrid { get; set; } = true; + + /// + /// Path to the item file this map uses, if any. + /// [DMProperty(name: "itemFile")] - public string Itemfile { get; set; } = string.Empty; - public CStoredCamera defaultcamera { get; set; } = []; + public string ItemFile { get; set; } = string.Empty; + + /// + /// Camera Hammer opens the map with. + /// + public CStoredCamera DefaultCamera { get; init; } = []; + + /// + /// Saved cameras. + /// [DMProperty(name: "3dcameras")] - public CStoredCameras Cameras { get; set; } = []; - public CMapWorld world { get; set; } = []; + public CStoredCameras Cameras { get; init; } = []; + + /// + /// Root of the map tree. + /// + public CMapWorld World { get; init; } = []; + + /// + /// Per node hidden state. Hammer writes this attribute with the misspelled name. + /// [DMProperty(name: "visbility")] - public CVisibilityMgr Visibility { get; set; } = []; + public CVisibilityMgr Visibility { get; init; } = []; + + /// + /// Map variables and their values. + /// [DMProperty(name: "mapVariables")] - public CMapVariableSet MapVariables { get; set; } = []; + public CMapVariableSet MapVariables { get; init; } = []; + + /// + /// Root of the selection set tree. + /// [DMProperty(name: "rootSelectionSet")] - public CMapSelectionSet RootSelectionSet { get; set; } = []; + public CMapSelectionSet RootSelectionSet { get; init; } = []; + + /// + /// Mesh snapshots the map references. + /// [DMProperty(name: "m_ReferencedMeshSnapshots")] - public Datamodel.ElementArray ReferencedMeshSnapshots { get; set; } = []; + public Datamodel.ElementArray ReferencedMeshSnapshots { get; init; } = []; + + /// + /// Whether the cordon is active. + /// [DMProperty(name: "m_bIsCordoning")] public bool IsCordoning { get; set; } + + /// + /// Whether cordon bounds are drawn. + /// [DMProperty(name: "m_bCordonsVisible")] public bool CordonsVisible { get; set; } + + /// + /// Per node instance data. + /// [DMProperty(name: "nodeInstanceData")] - public Datamodel.ElementArray NodeInstanceData { get; set; } = []; + public Datamodel.ElementArray NodeInstanceData { get; init; } = []; +} + +/// +/// A saved 3D viewport camera. +/// +[LowercaseProperties] +public class CStoredCamera : DMElement +{ + /// + /// Where the camera sits. + /// + public Vector3 Position { get; set; } = new Vector3(0, -1000, 1000); + + /// + /// What the camera points at. + /// + public Vector3 LookAt { get; set; } +} + +/// +/// The saved cameras of a map, and which one is active. +/// +[LowercaseProperties] +public class CStoredCameras : DMElement +{ + /// + /// Index into , -1 when none is active. + /// + [DMProperty(name: "activecamera")] + public int ActiveCameraIndex { get; set; } = -1; + + /// + /// List of elements. + /// + public Datamodel.ElementArray Cameras { get; init; } = []; +} + +/// +/// Base of everything that appears in the map tree: a transform, an id, and child nodes. +/// +[CamelCaseProperties] +public abstract class MapNode : DMElement +{ + /// + /// Position of the node, relative to its parent. + /// + public Vector3 Origin { get; set; } + + /// + /// Rotation of the node, relative to its parent. + /// + public Datamodel.QAngle Angles { get; set; } + + /// + /// Scale of the node, relative to its parent. + /// + public Vector3 Scales { get; set; } = new Vector3(1, 1, 1); + + /// + /// Id of the node within the map, referenced by and selection sets. + /// + public int NodeID { get; set; } + + /// + /// Id the node keeps across prefab and instance boundaries. + /// + public ulong ReferenceID { get; set; } + + /// + /// Child nodes parented to this one. + /// + public Datamodel.ElementArray Children { get; init; } = []; + + /// + /// Whether the node is stripped at compile time. + /// + public bool EditorOnly { get; set; } + + /// + /// Whether the node is hidden in Hammer. + /// + [DMProperty(name: "force_hidden")] + public bool ForceHidden { get; set; } + + /// + /// Whether Hammer refuses to move the node. + /// + public bool TransformLocked { get; set; } + + /// + /// Entity keys driven by a map variable, parallel to . + /// + public Datamodel.StringArray VariableTargetKeys { get; init; } = []; + + /// + /// Map variables driving . + /// + public Datamodel.StringArray VariableNames { get; init; } = []; + + /// + /// Pins the node's transform to another node, a plain "DmElement" holding the properties of . + /// + public DMElement TransformPin { get; init; } = new CMapTransformPin(); + + /// + /// Name of the custom vis group the node belongs to, empty for none. + /// + public string CustomVisGroup { get; set; } = string.Empty; + + /// + /// Seed Hammer uses for anything random about this node, such as smart prop evaluation. + /// + public int RandomSeed { get; set; } + + /// + /// Enumerates the child nodes of the given type, in order. + /// + /// Node class to filter by. + public IEnumerable GetChildren() where T : MapNode + { + foreach (var child in Children) + { + if (child is T typed) + { + yield return typed; + } + } + } +} + +/// +/// References another map file and places its contents at this node. +/// +[CamelCaseProperties] +public class CMapPrefab : MapNode +{ + /// + /// Output plugs of the prefab, one per entity IO connection. + /// + public DmePlugList RelayPlugData { get; init; } = []; + + /// + /// List of elements, one per entity IO connection. + /// + public Datamodel.ElementArray ConnectionsData { get; init; } = []; + + /// + /// The loaded contents of the prefab, null in a saved file. + /// + public DMElement? Target { get; init; } + + /// + /// Map variables of the prefab this node overrides, parallel to . + /// + public Datamodel.StringArray VariableOverrideNames { get; init; } = []; + + /// + /// Values for . + /// + public Datamodel.StringArray VariableOverrideValues { get; init; } = []; + + /// + /// Path to the map file this prefab pulls in. + /// + public string TargetMapPath { get; set; } = string.Empty; + + /// + /// Name given to the prefab instance. + /// + public string TargetName { get; set; } = string.Empty; + + /// + /// Whether entity names inside the prefab are prefixed to keep them unique. + /// + public bool FixupEntityNames { get; set; } = true; + + /// + /// Whether is used as the prefix for entity names instead of a generated one. + /// + public bool UseTargetNameAsPrefix { get; set; } + + /// + /// Whether the prefab still loads when it sits inside another prefab. + /// + public bool LoadIfNested { get; set; } = true; + + /// + /// Whether the prefab becomes an entity at runtime. + /// + public bool PrefabRuntimeEntity { get; set; } + + /// + /// Whether the prefab is spawned at runtime instead of merged at compile time. + /// + public bool LoadAtRuntime { get; set; } + + /// + /// Tint applied to everything in the prefab. + /// + public Datamodel.Color TintColor { get; set; } = new Datamodel.Color(255, 255, 255, 255); + + /// + /// Whether the prefab contents are left out of visibility computation. + /// + [DMProperty(name: "visexclude")] + public bool VisExclude { get; set; } +} + +/// +/// Base of every map node that carries entity key values and entity IO. +/// +[CamelCaseProperties] +public abstract class BaseEntity : MapNode +{ + /// + /// Output plugs this entity fires through, one per entity IO connection. + /// + public DmePlugList RelayPlugData { get; init; } = []; + + /// + /// List of elements, one per entity IO connection. + /// + public Datamodel.ElementArray ConnectionsData { get; init; } = []; + + /// + /// The entity key values, including "classname". + /// + [DMProperty(name: "entity_properties")] + public EditGameClassProps EntityProperties { get; init; } = []; + + /// + /// The "classname" key value, or null when the entity has none. + /// + public string? GetEntityClassName() => EntityProperties.TryGetValue("classname", out var value) ? value as string : null; + + /// + /// Sets one entity key value and returns this entity. + /// + /// Key to set. + /// Value to set it to. + public BaseEntity WithProperty(string name, string value) + { + EntityProperties[name] = value; + return this; + } + + /// + /// Sets several entity key values and returns this entity. + /// + /// Key value pairs to set. + public BaseEntity WithProperties(params (string name, string value)[] properties) + { + foreach (var (name, value) in properties) + { + EntityProperties[name] = value; + } + + return this; + } + + /// + /// Sets the "classname" key value and returns this entity. + /// + /// Entity class name. + public BaseEntity WithClassName(string className) + => WithProperty("classname", className); +} + +/// +/// The output plugs of an entity, stored as parallel arrays. +/// +[CamelCaseProperties] +public class DmePlugList : DMElement +{ + /// + /// Plug names. + /// + public Datamodel.StringArray Names { get; init; } = []; + + /// + /// Data type of each plug. + /// + public Datamodel.IntArray DataTypes { get; init; } = []; + + /// + /// Kind of each plug, input or output. + /// + public Datamodel.IntArray PlugTypes { get; init; } = []; + + /// + /// Description of each plug. + /// + public Datamodel.StringArray Descriptions { get; init; } = []; } +/// +/// One entity IO connection: an output firing an input on a target. +/// +[CamelCaseProperties] +public class DmeConnectionData : DMElement +{ + /// + /// Output that fires, for example "OnTrigger". + /// + public string OutputName { get; set; } = string.Empty; + + /// + /// How resolves to entities. + /// + public int TargetType { get; set; } + + /// + /// Entities the output fires at. + /// + public string TargetName { get; set; } = string.Empty; + + /// + /// Input fired on the target, for example "Enable". + /// + public string InputName { get; set; } = string.Empty; + + /// + /// Parameter passed to the input, overriding the output's own. + /// + public string OverrideParam { get; set; } = string.Empty; + + /// + /// Delay before the input fires, in seconds. + /// + public float Delay { get; set; } + + /// + /// How often the connection may fire, -1 for unlimited. + /// + public int TimesToFire { get; set; } = -1; +} + +/// +/// A string->string dictionary. This stores entity KeyValues. +/// +public class EditGameClassProps : DMElement +{ +} + +/// +/// The world entity. +/// +[CamelCaseProperties] +public class CMapWorld : BaseEntity +{ + /// + /// Next free decal id, handed out as decals are placed. + /// + public int NextDecalID { get; set; } + + /// + /// Whether entity names are prefixed to keep them unique across prefabs. + /// + public bool FixupEntityNames { get; set; } = true; + + /// + /// What the map is for, "standard" for a playable map. + /// + public string MapUsageType { get; set; } = "standard"; + + /// + /// Initializes a new instance of the class with classname "worldspawn". + /// + public CMapWorld() + { + EntityProperties["classname"] = "worldspawn"; + } +} + +/// +/// Per node hidden state, as two parallel arrays. +/// +[CamelCaseProperties] +public class CVisibilityMgr : MapNode +{ + /// + /// The nodes whose visibility is tracked. + /// + public Datamodel.ElementArray Nodes { get; init; } = []; + + /// + /// Hidden flags, one per entry of . 0 is visible, 1 hidden through a selection set, higher values quick hidden. + /// + public Datamodel.IntArray HiddenFlags { get; init; } = []; + + /// + /// Returns the hidden flags of a node, 0 when the node is visible or not tracked. + /// + /// Node to look up. + public int GetHiddenFlags(DMElement node) + { + var count = Math.Min(Nodes.Count, HiddenFlags.Count); + + for (var i = 0; i < count; i++) + { + if (Nodes[i]?.ID == node.ID) + { + return HiddenFlags[i]; + } + } + + return 0; + } + + /// + /// Whether a node is hidden in Hammer. + /// + /// Node to look up. + public bool IsHidden(DMElement node) => GetHiddenFlags(node) != 0; +} + +/// +/// Map variables, stored as parallel arrays of name, value, type and type parameters. +/// +[CamelCaseProperties] +public class CMapVariableSet : DMElement +{ + /// + /// Variable names. + /// + public Datamodel.StringArray VariableNames { get; init; } = []; + + /// + /// Variable values. + /// + public Datamodel.StringArray VariableValues { get; init; } = []; + + /// + /// Variable type names. + /// + public Datamodel.StringArray VariableTypeNames { get; init; } = []; + + /// + /// Parameters of the variable types, such as the options of a choice. + /// + public Datamodel.StringArray VariableTypeParameters { get; init; } = []; + + /// + /// Groups the choice variables are presented in. + /// + [DMProperty(name: "m_ChoiceGroups")] + public Datamodel.ElementArray ChoiceGroups { get; init; } = []; + + /// + /// Group each variable is shown under, parallel to . + /// + public Datamodel.StringArray VariableGroupNames { get; init; } = []; + + /// + /// Display order of the variables and choice groups. + /// + public Datamodel.IntArray VariableAndChoiceOrder { get; init; } = []; +} + +/// +/// A group of map variables presented as one choice. +/// +public class CMapVariableChoiceGroup : DMElement +{ + /// + /// Names of the variables the choice drives. + /// + [DMProperty(name: "m_ChoiceVariables")] + public Datamodel.StringArray ChoiceVariables { get; init; } = []; + + /// + /// The choices, each a plain element holding the values of . + /// + [DMProperty(name: "m_Choices")] + public Datamodel.ElementArray Choices { get; init; } = []; + + /// + /// Name of the active choice, empty for none. + /// + [DMProperty(name: "m_ActiveValue")] + public string ActiveValue { get; set; } = string.Empty; + + /// + /// Name shown for the group. + /// + [DMProperty(name: "m_GroupName")] + public string GroupName { get; set; } = string.Empty; +} + +/// +/// A named selection of map nodes, as shown in Hammer's selection set tree. +/// +[CamelCaseProperties] +public class CMapSelectionSet : DMElement +{ + /// + /// Nested selection sets. + /// + public Datamodel.ElementArray Children { get; init; } = []; + + /// + /// Name shown in Hammer. + /// + public string SelectionSetName { get; set; } = string.Empty; + + /// + /// What this set selects: a for whole nodes, or a + /// , or for mesh components. + /// + public DMElement SelectionSetData { get; init; } = new CObjectSelectionSetDataElement(); + + /// + /// The selection data when this set selects whole nodes, otherwise null. + /// + [SuppressMessage("Design", "CA1024:Use properties where appropriate", Justification = ValveMapSchema.SerializedPropertiesJustification)] + public CObjectSelectionSetDataElement? GetObjectSelection() => SelectionSetData as CObjectSelectionSetDataElement; + + /// + /// The selection data when this set selects faces, otherwise null. + /// + [SuppressMessage("Design", "CA1024:Use properties where appropriate", Justification = ValveMapSchema.SerializedPropertiesJustification)] + public CFaceSelectionSetDataElement? GetFaceSelection() => SelectionSetData as CFaceSelectionSetDataElement; + + /// + /// The nodes this set selects. + /// + /// Thrown when this is a face selection set. + public Datamodel.ElementArray GetSelectedObjects() + => GetObjectSelection()?.SelectedObjects ?? throw new InvalidOperationException($"Selection set '{SelectionSetName}' does not select objects."); + + /// + /// Enumerates this set and every set nested under it, depth first. + /// + public IEnumerable EnumerateSelectionSets() + { + yield return this; + + foreach (var child in Children) + { + if (child is not CMapSelectionSet childSet) + { + continue; + } + + foreach (var nested in childSet.EnumerateSelectionSets()) + { + yield return nested; + } + } + } + + /// + /// Initializes a new instance of the class. + /// + public CMapSelectionSet() { } + + /// + /// Initializes a new instance of the class with a name. + /// + /// Name shown in Hammer. + public CMapSelectionSet(string name) + { + SelectionSetName = name; + } +} + +/// +/// The map nodes a selects. +/// +[CamelCaseProperties] +public class CObjectSelectionSetDataElement : DMElement +{ + /// + /// The selected nodes. + /// + public Datamodel.ElementArray SelectedObjects { get; init; } = []; +} + +/// +/// The mesh faces a selects. +/// +[CamelCaseProperties] +public class CFaceSelectionSetDataElement : DMElement +{ + /// + /// The nodes that own the selected faces. + /// + public Datamodel.ElementArray Meshes { get; init; } = []; + + /// + /// Face indices into the meshes of . + /// + public Datamodel.IntArray Faces { get; init; } = []; +} + +/// +/// The mesh edges a selects. +/// +[CamelCaseProperties] +public class CEdgeSelectionSetDataElement : DMElement +{ + /// + /// Half edge indices into the meshes of . + /// + public Datamodel.IntArray Edges { get; init; } = []; + + /// + /// The nodes that own the selected edges. + /// + public Datamodel.ElementArray Meshes { get; init; } = []; +} + +/// +/// The mesh vertices a selects. +/// +[CamelCaseProperties] +public class CVertexSelectionSetDataElement : DMElement +{ + /// + /// Vertex indices into the meshes of . + /// + public Datamodel.IntArray Vertices { get; init; } = []; + + /// + /// The nodes that own the selected vertices. + /// + public Datamodel.ElementArray Meshes { get; init; } = []; +} + +/// +/// A point or brush entity placed in the map. +/// +[CamelCaseProperties] +public class CMapEntity : BaseEntity +{ + /// + /// Surface normal the entity was dropped onto when it was placed. + /// + public Vector3 HitNormal { get; set; } + + /// + /// Whether the entity was generated by a tool rather than placed by hand. + /// + public bool IsProceduralEntity { get; set; } + + /// + /// Returns the vertex paint data of a prop entity, or null when it has none. + /// Hammer only writes the "extra_vertex_data" attribute on painted props, so it is not a class property. + /// + [SuppressMessage("Design", "CA1024:Use properties where appropriate", Justification = ValveMapSchema.SerializedPropertiesJustification)] + public CDmExtraVertexData? GetExtraVertexData() + => TryGetValue("extra_vertex_data", out var value) ? value as CDmExtraVertexData : null; +} + +/// +/// Places another map group into the map with its own transform and tint. +/// +[CamelCaseProperties] +public class CMapInstance : MapNode +{ + /// + /// Output plugs of the instance, one per entity IO connection. + /// + public DmePlugList RelayPlugData { get; init; } = []; + + /// + /// List of elements, one per entity IO connection. + /// + public Datamodel.ElementArray ConnectionsData { get; init; } = []; + + /// + /// A target to instance. With custom tint and transform. + /// + public DMElement? Target { get; init; } + + /// + /// The instanced group, or null when is unset or not a group. + /// + [SuppressMessage("Design", "CA1024:Use properties where appropriate", Justification = ValveMapSchema.SerializedPropertiesJustification)] + public CMapGroup? GetTargetGroup() => Target as CMapGroup; + + /// + /// Tint applied to everything in the instance. + /// + public Datamodel.Color TintColor { get; set; } = new Datamodel.Color(255, 255, 255, 255); + + /// + /// Whether the instance contents are left out of visibility computation. + /// + [DMProperty(name: "visexclude")] + public bool VisExclude { get; set; } +} + +/// +/// Groups child nodes under one selectable node. Also the target of a . +/// +[CamelCaseProperties] +public class CMapGroup : MapNode +{ + /// + /// How the group deforms its children when it is scaled or sheared. + /// + public int DeformationMode { get; set; } +} + +/// +/// A named world layer, which is a map group that compiles into its own layer. +/// +[CamelCaseProperties] +public class CMapWorldLayer : CMapGroup +{ + /// + /// Name of the layer. + /// + public string WorldLayerName { get; set; } = string.Empty; +} + +/// +/// A mesh authored in Hammer, with its render, lighting and physics settings. +/// +[CamelCaseProperties] +public class CMapMesh : MapNode +{ + /// + /// Cubemap this mesh samples, empty to pick automatically. + /// + public string CubeMapName { get; set; } = string.Empty; + + /// + /// Light group this mesh belongs to. + /// + public string LightGroup { get; set; } = string.Empty; + + /// + /// Whether the mesh is left out of visibility computation. + /// + [DMProperty(name: "visexclude")] + public bool VisExclude { get; set; } + + /// + /// Whether the mesh renders in the dynamic pass. + /// + [DMProperty(name: "renderwithdynamic")] + public bool RenderWithDynamic { get; set; } + + /// + /// Whether height displacement is skipped for this mesh. + /// + public bool DisableHeightDisplacement { get; set; } + + /// + /// Distance at which the mesh starts fading out, -1 to never fade. + /// + [DMProperty(name: "fademindist")] + public float FadeMinDist { get; set; } = -1; + + /// + /// Distance at which the mesh is fully faded out. + /// + [DMProperty(name: "fademaxdist")] + public float FadeMaxDist { get; set; } + + /// + /// Whether the mesh takes part in baked lighting. + /// + [DMProperty(name: "bakelighting")] + public bool BakeLighting { get; set; } = true; + + /// + /// Whether light probes are precomputed around the mesh. + /// + [DMProperty(name: "precomputelightprobes")] + public bool PrecomputeLightProbes { get; set; } = true; + + /// + /// Whether the mesh appears in cubemap renders. + /// + public bool RenderToCubemaps { get; set; } = true; + + /// + /// Shadow casting mode, 0 to cast shadows. + /// + public int DisableShadows { get; set; } + + /// + /// Angle below which adjacent faces are shaded smooth, in degrees. + /// + public float SmoothingAngle { get; set; } = 40f; + + /// + /// Tint applied to the mesh. + /// + public Datamodel.Color TintColor { get; set; } = new Datamodel.Color(255, 255, 255, 255); + + /// + /// Render alpha, 0 to 255. + /// + [DMProperty(name: "renderAmt")] + public int RenderAmount { get; set; } = 255; + + /// + /// Physics model to build for the mesh. + /// + public string PhysicsType { get; set; } = "default"; + + /// + /// Collision group of the mesh. + /// + public string PhysicsGroup { get; set; } = string.Empty; + + /// + /// Collision categories the mesh counts as. + /// + public string PhysicsInteractsAs { get; set; } = string.Empty; + + /// + /// Collision categories the mesh collides with. + /// + public string PhysicsInteractsWith { get; set; } = string.Empty; + + /// + /// Collision categories the mesh never collides with. + /// + public string PhysicsInteractsExclude { get; set; } = string.Empty; + + /// + /// The geometry itself. + /// + public CDmePolygonMesh MeshData { get; init; } = []; + + /// + /// Whether the mesh occludes what is behind it. + /// + public bool UseAsOccluder { get; set; } + + /// + /// Whether overrides the default simplification. + /// + public bool PhysicsSimplificationOverride { get; set; } + + /// + /// Error the physics simplification is allowed to introduce. + /// + public float PhysicsSimplificationError { get; set; } + + /// + /// Whether emissive materials on the mesh light the scene when baking. + /// + public bool EmissiveLightingEnabled { get; set; } = true; + + /// + /// Multiplier on the emissive light the mesh contributes when baking. + /// + public float EmissiveLightingBoost { get; set; } = 1f; + + /// + /// Whether the mesh only exists to affect baked lighting and is not rendered. + /// + public bool LightingDummy { get; set; } + + /// + /// Whether both sides of the mesh receive baked lighting. + /// + public bool BakeLightDoubleSided { get; set; } + + /// + /// Whether the compiler must not merge this mesh with others. + /// + [DMProperty(name: "disablemerging")] + public bool DisableMerging { get; set; } + + /// + /// Whether the compiler keeps the vertices as authored instead of optimizing them. + /// + [DMProperty(name: "keep_vertices")] + public bool KeepVertices { get; set; } + + /// + /// Collision property overriding the one of the materials, empty for none. + /// + public string PhysicsCollisionProperty { get; set; } = string.Empty; + + /// + /// Detail layers whose geometry is included in this mesh's physics. + /// + public Datamodel.ElementArray PhysicsIncludedDetailLayers { get; init; } = []; + + /// + /// Detail layers whose geometry is left out of this mesh's physics. + /// + public Datamodel.ElementArray PhysicsMissingDetailLayers { get; init; } = []; +} + +/// +/// A decal which uses its own hammer editable mesh to project onto geometry. +/// +[CamelCaseProperties] +public class CMapStaticOverlay : CMapMesh +{ + /// + /// Node ids of the nodes the overlay projects onto. + /// + public Datamodel.IntArray ProjectionTargets { get; init; } = []; + + /// + /// Order the overlay is drawn in where overlays stack, higher on top. + /// + public int RenderOrder { get; set; } + + /// + /// Whether the overlay is left out at low quality settings. + /// + public bool DisabledInLowQuality { get; set; } + + /// + /// Whether the overlay shades with the normals of the surface under it rather than its own. + /// + public bool UseBaseNormals { get; set; } + + /// + /// How far from its mesh the overlay projects. + /// + public float ProjectionFar { get; set; } = 128f; + + /// + /// Adjustments applied to the decal material, a plain "DmElement" holding the properties of . + /// + [DMProperty(name: "MaterialAdjustmentParamsStruct")] + public DMElement MaterialAdjustmentParamsStruct { get; init; } = new CMapOverlayMaterialAdjustmentParams(); + + /// + /// Whether the overlay also lands on faces turned away from it. + /// + public bool ProjectOnBackFaces { get; set; } + + /// + /// Angle from the projection direction beyond which a face counts as facing away, in degrees. + /// + public float BackFacingAngle { get; set; } = 90f; + + /// + /// What the overlay projects onto: everything (0), world geometry (1), models (2) or its + /// (3). + /// + public int ProjectionMode { get; set; } +} + +/// +/// The material adjustments of a . +/// +public class CMapOverlayMaterialAdjustmentParams : DMElement +{ + /// + /// Initializes a new instance of the class with Hammer's defaults. + /// + public CMapOverlayMaterialAdjustmentParams() + { + ClassName = "DmElement"; + Name = "MaterialAdjustmentParamsStruct"; + } + + /// Colour brightness adjustment, 0.5 for none. + public float ColorBrightness { get; set; } = 0.5f; + + /// Colour contrast adjustment, 0.5 for none. + public float ColorContrast { get; set; } = 0.5f; + + /// Opacity of the colour. + public float ColorAlpha { get; set; } = 1f; + + /// Roughness brightness adjustment, 0.5 for none. + public float RoughnessBrightness { get; set; } = 0.5f; + + /// Roughness contrast adjustment, 0.5 for none. + public float RoughnessContrast { get; set; } = 0.5f; + + /// Opacity of the shading. + public float ShadingAlpha { get; set; } = 1f; + + /// Strength of the decal's normal map. + public float NormalIntensity { get; set; } = 0.75f; + + /// Whether the decal's roughness and metalness replace the surface's. + public bool RoughnessMetalnessOverride { get; set; } + + /// Whether the decal's normals blend over the surface's. + public bool NormalBlendOverride { get; set; } = true; +} + +/// +/// Hammer's editable mesh, stored as a half edge mesh with parallel index arrays and data streams. +/// +[CamelCaseProperties] +public class CDmePolygonMesh : DMElement +{ + /// + /// Index to one of the edges stemming from this vertex. + /// + public Datamodel.IntArray VertexEdgeIndices { get; init; } = []; + + /// + /// Index to the streams. + /// + public Datamodel.IntArray VertexDataIndices { get; init; } = []; + + /// + /// The destination vertex of this edge. + /// + public Datamodel.IntArray EdgeVertexIndices { get; init; } = []; + + /// + /// Index to the opposite/twin edge. + /// + public Datamodel.IntArray EdgeOppositeIndices { get; init; } = []; + + /// + /// Index to the next edge in the loop, in counter-clockwise order. + /// + public Datamodel.IntArray EdgeNextIndices { get; init; } = []; + + /// + /// Per half-edge index to the adjacent face. -1 if void (open edge). + /// + public Datamodel.IntArray EdgeFaceIndices { get; init; } = []; + + /// + /// Per half-edge index to the streams. + /// + public Datamodel.IntArray EdgeDataIndices { get; init; } = []; + + /// + /// Per half-edge index to the streams. + /// + public Datamodel.IntArray EdgeVertexDataIndices { get; init; } = []; + + /// + /// Per face index to one of the *inner* edges encapsulating this face. + /// + public Datamodel.IntArray FaceEdgeIndices { get; init; } = []; + + /// + /// Per face index to the streams. + /// + public Datamodel.IntArray FaceDataIndices { get; init; } = []; + + /// + /// List of material names. Indexed by the 'meshindex' stream. + /// + public Datamodel.StringArray Materials { get; init; } = []; + + /// + /// Stores vertex positions. + /// + public CDmePolygonMeshDataArray VertexData { get; init; } = []; + + /// + /// Stores vertex uv, normal, tangent, etc. Two per vertex (for each half?). + /// + public CDmePolygonMeshDataArray FaceVertexData { get; init; } = []; + + /// + /// Stores edge data such as soft or hard normals. + /// + public CDmePolygonMeshDataArray EdgeData { get; init; } = []; + + /// + /// Stores face data such as texture scale, UV offset, material, lightmap bias. + /// + public CDmePolygonMeshDataArray FaceData { get; init; } = []; + + /// + /// Stores the subdivision level of each half-edge. + /// + public CDmePolygonMeshSubdivisionData SubdivisionData { get; init; } = []; + + /// + /// Returns the number of faces in the mesh. + /// + [SuppressMessage("Design", "CA1024:Use properties where appropriate", Justification = ValveMapSchema.SerializedPropertiesJustification)] + public int GetFaceCount() => FaceEdgeIndices.Count; + + /// + /// Enumerates the half edges around a face, starting at its entry and following . + /// + /// Index of the face. + public IEnumerable GetFaceHalfEdges(int faceIndex) + { + var firstEdge = FaceEdgeIndices[faceIndex]; + var edge = firstEdge; + + do + { + yield return edge; + edge = EdgeNextIndices[edge]; + } + while (edge != firstEdge); + } + + /// + /// Enumerates the vertex indices around a face, in winding order. Index these into the streams through . + /// + /// Index of the face. + public IEnumerable GetFaceVertices(int faceIndex) + { + foreach (var edge in GetFaceHalfEdges(faceIndex)) + { + yield return EdgeVertexIndices[edge]; + } + } +} + +/// +/// A set of parallel data streams attached to one mesh component (vertices, half edges, or faces). +/// +[CamelCaseProperties] +public class CDmePolygonMeshDataArray : DMElement +{ + /// + /// Number of entries each stream in holds. + /// + public int Size { get; set; } + + /// + /// Array of . + /// + public Datamodel.ElementArray Streams { get; init; } = []; + + /// + /// Finds the stream with the given semantic name and index, for example "position" 0. + /// + /// Semantic name of the stream. + /// Channel of the semantic. + /// The stream, or null when there is none. + public CDmePolygonMeshDataStream? GetStream(string semanticName, int semanticIndex = 0) + { + foreach (var element in Streams) + { + if (element is CDmePolygonMeshDataStream stream && stream.SemanticIndex == semanticIndex && stream.SemanticName == semanticName) + { + return stream; + } + } + + return null; + } + + /// + /// Returns the data of the stream with the given semantic name and index as a typed array, or null when there is no such stream or its data has another type. + /// + /// Element type of the stream, int, Vector2, Vector3 or Vector4. + /// Semantic name of the stream. + /// Channel of the semantic. + public Datamodel.Array? GetStreamData(string semanticName, int semanticIndex = 0) + => GetStream(semanticName, semanticIndex)?.Data as Datamodel.Array; +} + +/// +/// Subdivision state of a . +/// +[CamelCaseProperties] +public class CDmePolygonMeshSubdivisionData : DMElement +{ + /// + /// Subdivision level per half edge. + /// + public Datamodel.IntArray SubdivisionLevels { get; init; } = []; + + /// + /// Array of . + /// + public Datamodel.ElementArray Streams { get; init; } = []; +} + +/// +/// One named data stream of a , such as position, uv, or material index. +/// +[CamelCaseProperties] +public class CDmePolygonMeshDataStream : DMElement +{ + /// + /// Name Hammer knows this stream by, for example "position" or "texcoord". + /// + public string StandardAttributeName { get; set; } = string.Empty; + + /// + /// Name the stream binds to in the shader, for example "position" or "normal". + /// + public string SemanticName { get; set; } = string.Empty; + + /// + /// Channel of this stream fills. + /// + public int SemanticIndex { get; set; } + + /// + /// Slot this stream occupies in the vertex buffer. + /// + public int VertexBufferLocation { get; set; } + + /// + /// Flags describing how the stream is stored. + /// + public int DataStateFlags { get; set; } + + /// + /// Subdivision stream this one mirrors, or null. + /// + public DMElement? SubdivisionBinding { get; init; } + + /// + /// An int, vector2, vector3, or vector4 array: , , + /// or . + /// + public IList? Data { get; init; } +} + +/// +/// Pins a node's transform to another node, stored as a plain "DmElement" named "transformPin". +/// +[CamelCaseProperties] +public class CMapTransformPin : DMElement +{ + /// + /// Initializes a new instance of the class with Hammer's defaults. + /// + public CMapTransformPin() + { + ClassName = "DmElement"; + Name = "transformPin"; + } + + /// + /// Name of the node this one is pinned to, empty when not pinned. + /// + public string ReferenceName { get; set; } = string.Empty; + + /// + /// Reference id of the node this one is pinned to, 0 when not pinned. + /// + public ulong TargetReferenceID { get; set; } + + /// + /// Offset kept from the pinned node. + /// + public Vector3 OffsetOrigin { get; set; } + + /// + /// Rotation kept relative to the pinned node. + /// + public Datamodel.QAngle OffsetAngles { get; set; } + + /// + /// Whether the rotation follows the pinned node too. + /// + public bool PinAngles { get; set; } = true; + + /// + /// Whether moving this node also moves the pinned node. + /// + public bool TwoWay { get; set; } +} + +/// +/// A spline of children, the base of cables and particle paths. +/// +[CamelCaseProperties] +public class CMapPath : CMapEntity +{ + /// + /// How the spline interpolates between its nodes. + /// + public int InterpolationType { get; set; } + + /// + /// Whether the last node connects back to the first. + /// + public bool ClosedLoop { get; set; } + + /// + /// Distance between the points a particle snapshot samples along the path. + /// + public float ParticleSnapshotSpacing { get; set; } = 16f; +} + +/// +/// One control point of a . +/// +[CamelCaseProperties] +public class CMapPathNode : CMapEntity +{ + /// + /// Tangent of the spline entering this node. + /// + public Vector3 InTangent { get; set; } + + /// + /// Tangent of the spline leaving this node. + /// + public Vector3 OutTangent { get; set; } -internal class CStoredCamera : DMElement -{ - public Vector3 position { get; set; } = new Vector3(0, -1000, 1000); - public Vector3 lookat { get; set; } -} + /// + /// How is computed. + /// + public int InTangentType { get; set; } = 1; + /// + /// How is computed. + /// + public int OutTangentType { get; set; } = 1; +} -internal class CStoredCameras : DMElement +/// +/// A cable rendered as a tube swept along a . +/// +[CamelCaseProperties] +public class CMapCable : CMapPath { - [DMProperty(name: "activecamera")] - public int ActiveCameraIndex { get; set; } = -1; - public Datamodel.ElementArray cameras { get; set; } = []; -} + /// + /// Material of the cable. + /// + public string MaterialName { get; set; } = string.Empty; + /// + /// Tint applied to the cable. + /// + public Datamodel.Color TintColor { get; set; } = new Datamodel.Color(255, 255, 255, 255); -internal abstract class MapNode : DMElement -{ - public Vector3 origin { get; set; } - public Datamodel.QAngle angles { get; set; } - public Vector3 scales { get; set; } = new Vector3(1, 1, 1); + /// + /// Name of the entity the cable takes its lighting from, empty for none. + /// + public string LightingOriginName { get; set; } = string.Empty; - public int nodeID { get; set; } - public ulong referenceID { get; set; } + /// + /// Number of sides of the tube. + /// + public int NumSides { get; set; } = 4; - public Datamodel.ElementArray children { get; set; } = []; + /// + /// Distance between the rings of the tube along the path. + /// + public float TessellationSpacing { get; set; } = 16f; - public bool editorOnly { get; set; } - [DMProperty(name: "force_hidden")] - public bool ForceHidden { get; set; } - public bool transformLocked { get; set; } - public Datamodel.StringArray variableTargetKeys { get; set; } = []; - public Datamodel.StringArray variableNames { get; set; } = []; -} + /// + /// Radius of the tube. + /// + public float Radius { get; set; } = 0.5f; -internal class CMapPrefab : MapNode -{ - public bool fixupEntityNames { get; set; } = true; - public bool loadAtRuntime { get; set; } - public bool loadIfNested { get; set; } = true; - public string targetMapPath { get; set; } = string.Empty; - public string targetName { get; set; } = string.Empty; -} + /// + /// Whether the tube faces inwards. + /// + public bool FlipFaces { get; set; } + /// + /// Whether the texture runs along the path (0) or around it (1). + /// + public int TextureOrientation { get; set; } -internal abstract class BaseEntity : MapNode -{ - public DmePlugList relayPlugData { get; set; } = []; - public Datamodel.ElementArray connectionsData { get; set; } = []; - [DMProperty(name: "entity_properties")] - public EditGameClassProps EntityProperties { get; set; } = []; + /// + /// Texture repeats per unit along the path. + /// + public float TextureScale { get; set; } = 0.25f; - public BaseEntity WithProperty(string name, string value) - { - EntityProperties[name] = value; - return this; - } + /// + /// Texture repeats around the circumference. + /// + public float TextureRepeatsCircumference { get; set; } = 1f; - public BaseEntity WithProperties(params (string name, string value)[] properties) - { - foreach (var (name, value) in properties) - { - EntityProperties[name] = value; - } + /// + /// Texture offset along the path. + /// + public float TextureOffsetAlongPath { get; set; } - return this; - } + /// + /// Texture offset around the circumference. + /// + public float TextureOffsetCircumference { get; set; } - public BaseEntity WithClassName(string className) - => WithProperty("classname", className); -} + /// + /// Whether the cable gets physics geometry. + /// + public bool CollisionEnabled { get; set; } + /// + /// Error the physics simplification is allowed to introduce. + /// + public float PhysicsSimplificationError { get; set; } = 2f; -internal class DmePlugList : DMElement -{ - public Datamodel.StringArray names { get; set; } = []; - public Datamodel.IntArray dataTypes { get; set; } = []; - public Datamodel.IntArray plugTypes { get; set; } = []; - public Datamodel.StringArray descriptions { get; set; } = []; + /// + /// Whether the cable occludes what is behind it. + /// + public bool VisOccluder { get; set; } } - -internal class DmeConnectionData : DMElement +/// +/// The cordon box, whose transform is the box: is its centre and its size. +/// +public class CMapCordon : MapNode { - public string outputName { get; set; } = string.Empty; - public int targetType { get; set; } - public string targetName { get; set; } = string.Empty; - public string inputName { get; set; } = string.Empty; - public string overrideParam { get; set; } = string.Empty; - public float delay { get; set; } - public int timesToFire { get; set; } = -1; + /// + /// Initializes a new instance of the class named as Hammer does. + /// + public CMapCordon() + { + Name = "cordon"; + } } /// -/// A string->string dictionary. This stores entity KeyValues. +/// Node holding the navigation mesh generation settings of the map. /// -internal class EditGameClassProps : DMElement +[CamelCaseProperties] +public class CMapNavData : MapNode { + /// + /// The settings. + /// + public CDmeNavData NavData { get; init; } = []; } /// -/// The world entity. +/// Navigation mesh generation settings. Per agent hull values are parallel arrays with entries. /// - -internal class CMapWorld : BaseEntity +[CamelCaseProperties] +public class CDmeNavData : DMElement { - public int nextDecalID { get; set; } - public bool fixupEntityNames { get; set; } = true; - public string mapUsageType { get; set; } = "standard"; - - public CMapWorld() + /// + /// Initializes a new instance of the class named as Hammer does. + /// + public CDmeNavData() { - EntityProperties["classname"] = "worldspawn"; + Name = "navData"; } -} + /// Whether the project defaults override the settings stored here. + public bool SettingsUseProjectDefaults { get; set; } = true; -internal class CVisibilityMgr : MapNode -{ - public Datamodel.ElementArray nodes { get; set; } = []; - public Datamodel.IntArray hiddenFlags { get; set; } = []; -} + /// Size of a navigation tile, in units. + public float SettingsTileSize { get; set; } = 128f; + /// Size of a voxel cell, in units. + public float SettingsCellSize { get; set; } = 1.5f; -internal class CMapVariableSet : DMElement -{ - public Datamodel.StringArray variableNames { get; set; } = []; - public Datamodel.StringArray variableValues { get; set; } = []; - public Datamodel.StringArray variableTypeNames { get; set; } = []; - public Datamodel.StringArray variableTypeParameters { get; set; } = []; - [DMProperty(name: "m_ChoiceGroups")] - public Datamodel.ElementArray ChoiceGroups { get; set; } = []; -} + /// Height of a voxel cell, in units. + public float SettingsCellHeight { get; set; } = 2f; + /// Smallest region kept, in cells. + public int SettingsRegionMinSize { get; set; } = 8; -[CamelCaseProperties] -internal class CMapSelectionSet : DMElement -{ - public Datamodel.ElementArray Children { get; } = []; - public string SelectionSetName { get; set; } = string.Empty; - public DMElement SelectionSetData { get; set; } = []; + /// Regions smaller than this are merged, in cells. + public int SettingsRegionMergeSize { get; set; } = 20; - public CMapSelectionSet() { } - public CMapSelectionSet(string name) - { - SelectionSetName = name; - } -} + /// Sampling distance of the detail mesh. + public float SettingsDetailSampleDist { get; set; } = 120f; + /// Error the detail mesh is allowed to introduce. + public float SettingsDetailSampleMaxError { get; set; } = 2f; -internal class CObjectSelectionSetDataElement : DMElement -{ - public Datamodel.ElementArray selectedObjects { get; set; } = []; -} + /// Maximum vertices per navigation polygon. + public int SettingsVertsPerPoly { get; set; } = 4; -internal class CFaceSelectionSetDataElement : DMElement -{ - public Datamodel.IntArray faces { get; set; } = []; - public Datamodel.ElementArray meshes { get; set; } = []; -} + /// Longest polygon edge, in cells. + public int SettingsEdgeMaxLen { get; set; } = 1200; + /// Error an edge is allowed to deviate from the geometry. + public float SettingsEdgeMaxError { get; set; } = 45f; -internal class CMapEntity : BaseEntity -{ - public Vector3 hitNormal { get; set; } - public bool isProceduralEntity { get; set; } -} + /// Areas on edges smaller than this are removed, -1 to keep them. + public float SettingsSmallAreaOnEdgeRemovalSize { get; set; } = -1f; + /// Name of the agent hull preset, empty for none. + public string SettingsAgentHullPreset { get; set; } = string.Empty; -[LowercaseProperties] -internal class CMapInstance : BaseEntity + /// Path of the vdata overriding the agent hulls, empty for none. + public string SettingsAgentHullsVDataOverride { get; set; } = string.Empty; + + /// Number of agent hulls. + public int SettingsAgentNumHulls { get; set; } = 1; + + /// Whether each hull is generated. + public Datamodel.BoolArray SettingsAgentEnabled { get; init; } = [true]; + + /// Radius of each hull. + public Datamodel.FloatArray SettingsAgentRadius { get; init; } = [15f]; + + /// Height of each hull. + public Datamodel.FloatArray SettingsAgentHeight { get; init; } = [71f]; + + /// Whether each hull has a crouching height. + public Datamodel.BoolArray SettingsAgentShortHeightEnabled { get; init; } = [false]; + + /// Crouching height of each hull. + public Datamodel.FloatArray SettingsAgentShortHeight { get; init; } = [35.5f]; + + /// Whether each hull has a crawling height. + public Datamodel.BoolArray SettingsAgentCrawlEnabled { get; init; } = [false]; + + /// Crawling height of each hull. + public Datamodel.FloatArray SettingsAgentCrawlHeight { get; init; } = [17.5f]; + + /// Highest step each hull can climb. + public Datamodel.FloatArray SettingsAgentMaxClimb { get; init; } = [17.5f]; + + /// Steepest slope each hull can walk, in degrees. + public Datamodel.IntArray SettingsAgentMaxSlope { get; init; } = [50]; + + /// Furthest each hull can jump down. + public Datamodel.FloatArray SettingsAgentMaxJumpDownDist { get; init; } = [240f]; + + /// Furthest each hull can jump horizontally. + public Datamodel.FloatArray SettingsAgentMaxJumpHorizDistBase { get; init; } = [64f]; + + /// Highest each hull can jump up. + public Datamodel.FloatArray SettingsAgentMaxJumpUpDist { get; init; } = [0f]; + + /// Cells eroded from the border for each hull, -1 for the default. + public Datamodel.IntArray SettingsAgentBorderErosion { get; init; } = [-1]; +} + +/// +/// A smart prop placed in the map, evaluated by Hammer into the props it stands for. +/// +[CamelCaseProperties] +public class CMapSmartProp : MapNode { /// - /// A target to instance. With custom tint and transform. + /// Nodes the smart prop shapes itself around, each wrapped in a plain element with a "value" attribute. /// - public CMapGroup? Target { get; set; } - public Datamodel.Color TintColor { get; set; } = new Datamodel.Color(255, 255, 255, 255); -} + public Datamodel.ElementArray ShapeReferences { get; init; } = []; -internal class CMapGroup : MapNode -{ -} + /// + /// Path of the smart prop definition. + /// + public string SmartPropFilename { get; set; } = string.Empty; + /// + /// Tint applied to the evaluated props. + /// + public Datamodel.Color TintColor { get; set; } = new Datamodel.Color(255, 255, 255, 255); -internal class CMapWorldLayer : CMapGroup -{ - public string worldLayerName { get; set; } = string.Empty; -} + /// + /// Whether Hammer keeps the current evaluation instead of re-evaluating on changes. + /// + public bool EvaluationLocked { get; set; } + /// + /// Whether the evaluation is constrained to the prefab the smart prop sits in. + /// + public bool ConstrainToPrefab { get; set; } -internal class CMapMesh : MapNode -{ - public string cubeMapName { get; set; } = string.Empty; - public string lightGroup { get; set; } = string.Empty; - [DMProperty(name: "visexclude")] - public bool VisExclude { get; set; } - [DMProperty(name: "renderwithdynamic")] - public bool RenderWithDynamic { get; set; } - public bool disableHeightDisplacement { get; set; } - [DMProperty(name: "fademindist")] - public float FadeMinDist { get; set; } = -1; - [DMProperty(name: "fademaxdist")] - public float FadeMaxDist { get; set; } - [DMProperty(name: "bakelighting")] - public bool BakeLighting { get; set; } = true; - [DMProperty(name: "precomputelightprobes")] - public bool PrecomputeLightProbes { get; set; } = true; - public bool renderToCubemaps { get; set; } = true; - public int disableShadows { get; set; } - public float smoothingAngle { get; set; } = 40f; - public Datamodel.Color tintColor { get; set; } = new Datamodel.Color(255, 255, 255, 255); - [DMProperty(name: "renderAmt")] - public int RenderAmount { get; set; } = 255; - public string physicsType { get; set; } = "default"; - public string physicsGroup { get; set; } = string.Empty; - public string physicsInteractsAs { get; set; } = string.Empty; - public string physicsInteractWsith { get; set; } = string.Empty; - public string physicsInteractsExclude { get; set; } = string.Empty; - public CDmePolygonMesh meshData { get; set; } = []; - public bool useAsOccluder { get; set; } - public bool physicsSimplificationOverride { get; set; } - public float physicsSimplificationError { get; set; } -} + /// + /// Render alpha, 0 to 255. + /// + public int Alpha { get; set; } = 255; + /// + /// Distance beyond which the props are culled, 0 for never. + /// + public float CullDistance { get; set; } -internal class CDmePolygonMesh : MapNode -{ /// - /// Index to one of the edges stemming from this vertex. + /// Distance at which the props start fading out, -1 to never fade. /// - public Datamodel.IntArray vertexEdgeIndices { get; set; } = []; + public float FadeStartDistance { get; set; } = -1f; /// - /// Index to the streams. + /// Name of the entity the props take their lighting from, empty for none. /// - public Datamodel.IntArray vertexDataIndices { get; set; } = []; + public string LightingOriginName { get; set; } = string.Empty; /// - /// The destination vertex of this edge. + /// Shadow casting mode, 0 to cast shadows. /// - public Datamodel.IntArray edgeVertexIndices { get; set; } = []; + public int DisableShadows { get; set; } /// - /// Index to the opposite/twin edge. + /// How the props take part in baked lighting, -1 for the default. Hammer stores this attribute with the misspelled name. /// - public Datamodel.IntArray edgeOppositeIndices { get; set; } = []; + [DMProperty(name: "bakedLigthtingMode")] + public int BakedLightingMode { get; set; } = -1; /// - /// Index to the next edge in the loop, in counter-clockwise order. + /// Lightmap resolution bias of the props. /// - public Datamodel.IntArray edgeNextIndices { get; set; } = []; + public int LightmapScaleBias { get; set; } /// - /// Per half-edge index to the adjacent face. -1 if void (open edge). + /// Whether both sides of the props receive baked lighting. /// - public Datamodel.IntArray edgeFaceIndices { get; set; } = []; + public bool BakeLightingDoubleSided { get; set; } /// - /// Per half-edge index to the streams. + /// Whether emissive materials on the props light the scene when baking. /// - public Datamodel.IntArray edgeDataIndices { get; set; } = []; + public bool EmissiveLightingEnabled { get; set; } = true; /// - /// Per half-edge index to the streams. + /// Multiplier on the emissive light the props contribute when baking. /// - public Datamodel.IntArray edgeVertexDataIndices { get; set; } = []; + public float EmissiveLightingBoost { get; set; } = 1f; /// - /// Per face index to one of the *inner* edges encapsulating this face. + /// Collision mode of the props, -1 for the default. /// - public Datamodel.IntArray faceEdgeIndices { get; set; } = []; + public int CollisionMode { get; set; } = -1; /// - /// Per face index to the streams. + /// Collision property overriding the one of the props' materials, empty for none. /// - public Datamodel.IntArray faceDataIndices { get; set; } = []; + public string CollisionPropertyOverride { get; set; } = string.Empty; /// - /// List of material names. Indexed by the 'meshindex' stream. + /// Whether the props occlude what is behind them. /// - public Datamodel.StringArray materials { get; set; } = []; + public bool IsVisOccluder { get; set; } /// - /// Stores vertex positions. + /// Whether the props appear in cubemap renders. /// - public CDmePolygonMeshDataArray vertexData { get; set; } = []; + public bool RenderToCubeMaps { get; set; } = true; /// - /// Stores vertex uv, normal, tangent, etc. Two per vertex (for each half?). + /// Whether the props are left out at low quality settings. /// - public CDmePolygonMeshDataArray faceVertexData { get; set; } = []; + public bool DisabledInLowQuality { get; set; } /// - /// Stores edge data such as soft or hard normals. + /// Whether the props are baked into the world geometry. /// - public CDmePolygonMeshDataArray edgeData { get; set; } = []; + public bool BakeToWorld { get; set; } /// - /// Stores face data such as texture scale, UV offset, material, lightmap bias. + /// Whether the compiler must not merge the props with others. /// - public CDmePolygonMeshDataArray faceData { get; set; } = []; + public bool DisableMerging { get; set; } - public CDmePolygonMeshSubdivisionData subdivisionData { get; set; } = []; + /// + /// Whether the props render in the dynamic pass. + /// + public bool RenderWithDynamic { get; set; } + + /// + /// The evaluated state of the smart prop, a plain "DmElement" named "nodeData" holding its parameters and configuration. + /// + public DMElement NodeData { get; init; } = new DMElement { ClassName = "DmElement", Name = "nodeData" }; } +/// +/// Baked per vertex lighting of one node, stored in the root's and named after the node id. +/// +[CamelCaseProperties] +public class CDmeNodeInstanceData : DMElement +{ + /// + /// Baked light colour per vertex. + /// + public Datamodel.ColorArray VertexLightingData { get; init; } = []; + + /// + /// Position of each baked vertex. + /// + public Datamodel.Vector3Array VertexLightingPositions { get; init; } = []; + + /// + /// Normal of each baked vertex. + /// + public Datamodel.Vector3Array VertexLightingNormals { get; init; } = []; +} -internal class CDmePolygonMeshDataArray : DMElement +/// +/// The render geometry of a model the map references, kept so that vertex paint can be applied to it. +/// +public class CDmeReferencedMeshSnapshot : DMElement { - public int size { get; set; } /// - /// Array of . + /// Path of the model. + /// + [DMProperty(name: "m_MeshResourceName")] + public string MeshResourceName { get; set; } = string.Empty; + + /// + /// List of elements, one per draw call of the model. /// - public Datamodel.ElementArray streams { get; set; } = []; + [DMProperty(name: "m_DrawCalls")] + public Datamodel.ElementArray DrawCalls { get; init; } = []; } +/// +/// The vertices of one draw call of a . +/// +public class CDmeDrawCallSnapshot : DMElement +{ + /// + /// Vertex positions. + /// + [DMProperty(name: "m_Positions")] + public Datamodel.Vector3Array Positions { get; init; } = []; + + /// + /// Vertex normals. + /// + [DMProperty(name: "m_Normals")] + public Datamodel.Vector3Array Normals { get; init; } = []; + + /// + /// Vertex texture coordinates. + /// + [DMProperty(name: "m_Texcoords")] + public Datamodel.Vector2Array Texcoords { get; init; } = []; + + /// + /// Hash of the draw call, used to match it to the compiled model. + /// + [DMProperty(name: "m_nHash")] + public int Hash { get; set; } + + /// + /// Material of the draw call. + /// + [DMProperty(name: "m_Material")] + public string Material { get; set; } = string.Empty; +} -internal class CDmePolygonMeshSubdivisionData : DMElement +/// +/// Binds a to the subdivision data that drives it. +/// +[CamelCaseProperties] +public class CDmePolygonMeshSubdivisiondataBinding : DMElement { - public Datamodel.IntArray subdivisionLevels { get; set; } = []; /// - /// Array of . + /// Initializes a new instance of the class named as Hammer does. + /// + public CDmePolygonMeshSubdivisiondataBinding() + { + Name = "subdivisionBinding"; + } + + /// + /// Mesh component the target stream belongs to, -1 for none. + /// + public int TargetDataType { get; set; } = -1; + + /// + /// Index of the target stream within its component, -1 for none. + /// + public int TargetStreamIndex { get; set; } = -1; + + /// + /// Where the subdivided values come from. /// - public Datamodel.ElementArray streams { get; set; } = []; + public int StreamSourceType { get; set; } } -internal class CDmePolygonMeshDataStream : DMElement +/// +/// Vertex paint applied to a prop entity, stored on the entity as "extra_vertex_data". +/// +public class CDmExtraVertexData : DMElement { - public string standardAttributeName { get; set; } = string.Empty; - public string semanticName { get; set; } = string.Empty; - public int semanticIndex { get; set; } - public int vertexBufferLocation { get; set; } - public int dataStateFlags { get; set; } - public DMElement? subdivisionBinding { get; set; } /// - /// An int, vector2, vector3, or vector4 array. + /// List of elements, one per painted draw call. /// - public System.Collections.IList? data { get; set; } + [DMProperty(name: "m_ExtraStreams")] + public Datamodel.ElementArray ExtraStreams { get; init; } = []; } -/// -/// Note: The deserializer does not support generic types, but the serializer does. -/// -/// Int, Vector2, Vector3, or Vector4 -internal class CDmePolygonMeshDataStream : CDmePolygonMeshDataStream +/// +/// Vertex paint of one draw call of a prop. +/// +public class CDmExtraVertexStream : DMElement { - public new required Datamodel.Array data { get; set; } + /// + /// Index of the draw call within the mesh. + /// + [DMProperty(name: "m_nDrawCallIndex")] + public int DrawCallIndex { get; set; } + + /// + /// Index of the mesh within the model. + /// + [DMProperty(name: "m_nMeshIndex")] + public int MeshIndex { get; set; } + + /// + /// A "DmeVertexData" element holding the painted streams, such as "VertexPaintTintColor" and "PerVertexLighting", each with an "Indices" array. + /// + [DMProperty(name: "m_pVertexData")] + public DMElement? VertexData { get; init; } } From 6a70fb07e0e1b6c230920240d8203d753987cfa9 Mon Sep 17 00:00:00 2001 From: Angel Date: Fri, 4 Sep 2026 11:56:22 +0200 Subject: [PATCH 12/13] Add round trip tests --- .../prefabs/roundtrip_test_prefab1.vmap | Bin 0 -> 9780 bytes .../prefabs/roundtrip_test_prefab2.vmap | Bin 0 -> 15904 bytes .../prefabs/roundtrip_test_prefab3.vmap | Bin 0 -> 19973 bytes Tests/Resources/roundtrip_test.vmap | Bin 0 -> 676225 bytes Tests/RoundTripTests.cs | 356 ++++++++++++++++++ 5 files changed, 356 insertions(+) create mode 100644 Tests/Resources/prefabs/roundtrip_test_prefab1.vmap create mode 100644 Tests/Resources/prefabs/roundtrip_test_prefab2.vmap create mode 100644 Tests/Resources/prefabs/roundtrip_test_prefab3.vmap create mode 100644 Tests/Resources/roundtrip_test.vmap create mode 100644 Tests/RoundTripTests.cs diff --git a/Tests/Resources/prefabs/roundtrip_test_prefab1.vmap b/Tests/Resources/prefabs/roundtrip_test_prefab1.vmap new file mode 100644 index 0000000000000000000000000000000000000000..739440256f47032df3a29b06a75e5119cc300b55 GIT binary patch literal 9780 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 literal 0 HcmV?d00001 diff --git a/Tests/Resources/prefabs/roundtrip_test_prefab2.vmap b/Tests/Resources/prefabs/roundtrip_test_prefab2.vmap new file mode 100644 index 0000000000000000000000000000000000000000..3368ff64d8605154bc559080d63ffcfd8e5118af GIT binary patch literal 15904 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%0DFmrVk_eKK#DJ!NxKNb4 zK`jX;OK=x}C}J=X?j8*w-2JMS2m8i$yz34-s&tjIR3Rz}7w0OnUHo2TqPQk3SAJ|K zFrF337qrY9ph{#{_VjK(Xc{EyGP2zR5F?`RZ?WndLYpuH*S9c3=YEsMZ#g;bSz!hm zhZ{x<(3$42#*8xSxu7v$gi4XeJaclh2Gb!C&6QRg^jnOU{S%|5mx$3$?$;%CX}bw6 z&NAsMAsf{Q$*&tOEggBdxp%#B&6ALz!Ic%Dn5gAQMVwhCvQHqzBvlM}oLOb5NKI#0 zBJg67KE^a^k-(24WtHa_ngHhs!Jlttqw&qy8y#Xf>$E&**nM}pZB%#z?C z2_6KXizqWCcmNYL5hNPITQK-$MLuklLd>&4=J}R+mXXIiI~rsTwz{2f8bxpk=)LqlT8S2-w{op=E?)-4{tuFuB-jH$J<5v`ydc4D0C6|i z1<;*4-9_FI#W{gs4=9?7UX(!G@p&pZ|4Wyx z`aj^R*cl`LmE#H9MxpL}9?rpbP&5zQ_EoVfGVvfDp6pK5Toq$^LliDd5W$6`P!#6E zHCM$mua@%uV%=9lysYM`2>-!z##Pt4WGEG)*t|AUF2s})Q$pg zB0wz(_$#pBL=mJzhChf1&d;*ePZIn{a2mlRsI~5jfbU#iHTt1KClKcL7kX7+)Q;>`HD5Jg9`T%Y z!8C$M%~y?@uNrUzh87a{PEsw47z;?T7S+a^#3fJS7E7vU5u-J!fkn^Y{h#^+_&|(p z4Je8+SA5k-1rT2~xTUUQ(G5sw&uyUJ!w=v$q8~f~B!ZGa$spdGIhQYk{y+Z!F22)q zaPqM}3CNS7WQXQM@tO5)tNgpZY9v}+W>k;$BpF2^34P2Sm54`Kp04F5_An z$Trn4`$`jb?xbzcbL+4~QOGB}znrvm0dpeN)X3;9;wR7PCzZ^UJ*C ziM*V$3oWk@>Z;MtiP{c|=5cE)NW`^40QThme!pt4^L61@(c-_;0JH!@_#XSr10$Ys PaJq4+^-*duO!mJ3VqIs$ literal 0 HcmV?d00001 diff --git a/Tests/Resources/roundtrip_test.vmap b/Tests/Resources/roundtrip_test.vmap new file mode 100644 index 0000000000000000000000000000000000000000..055dd75b74547fea2723cdc66de42c0e85e68473 GIT binary patch literal 676225 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 literal 0 HcmV?d00001 diff --git a/Tests/RoundTripTests.cs b/Tests/RoundTripTests.cs new file mode 100644 index 0000000..7c94376 --- /dev/null +++ b/Tests/RoundTripTests.cs @@ -0,0 +1,356 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Numerics; +using NUnit.Framework; +using Datamodel; +using Tests.VMAP; +using DM = Datamodel.Datamodel; + +namespace Datamodel_Tests +{ + /// + /// Loading a file and saving it again must reproduce every element, every attribute and the prefix attributes, + /// whether the elements were deserialized as plain s or as typed subclasses. + /// + [TestFixture] + public class RoundTripTests + { + static string Resource(string name) => Path.Combine(TestContext.CurrentContext.TestDirectory, "Resources", name); + + // a map made for this purpose: every node class, all selection set kinds, nested prefabs and instances, + // subdivision, vertex paint, baked lighting, a thumbnail and asset references in the prefix + static readonly string[] VmapFiles = + [ + "roundtrip_test.vmap", + Path.Combine("prefabs", "roundtrip_test_prefab1.vmap"), + Path.Combine("prefabs", "roundtrip_test_prefab2.vmap"), + Path.Combine("prefabs", "roundtrip_test_prefab3.vmap"), + ]; + + [Test, TestCaseSource(nameof(VmapFiles))] + public void Binary_Untyped(string file) + { + using var original = DM.Load(Resource(file), Datamodel.Codecs.DeferredMode.Disabled); + var saved = Save(original); + + using var reloaded = DM.Load(saved); + AssertEquivalent(original, reloaded, orderSensitive: true); + Assert.That(reloaded.PrefixElementId, Is.EqualTo(original.PrefixElementId)); + + Assert.That(Save(reloaded), Is.EqualTo(saved), "saving the reloaded datamodel must reproduce the same bytes"); + } + + [Test, TestCaseSource(nameof(VmapFiles))] + public void Binary_PrefixElementIsNotAnOrphan(string file) + { + using var dm = DM.Load(Resource(file), Datamodel.Codecs.DeferredMode.Disabled); + + Assert.That(dm.PrefixAttributes.Keys, Does.Contain("map_asset_references")); + + var reachable = new HashSet(); + Visit(dm.Root); + Assert.That(dm.AllElements.Count, Is.EqualTo(reachable.Count), "every element must be reachable from the root"); + + void Visit(Element? element) + { + if (element == null || !reachable.Add(element)) + return; + + foreach (var attr in element) + { + if (attr.Value is Element child) + Visit(child); + else if (attr.Value is IEnumerable children) + foreach (var arrayChild in children) + Visit(arrayChild); + } + } + } + + [Test, TestCaseSource(nameof(VmapFiles))] + public void Binary_Typed(string file) + { + using var original = DM.Load(Resource(file), Datamodel.Codecs.DeferredMode.Disabled); + using var typed = DM.Load(Resource(file)); + + Assert.That(typed.Root, Is.TypeOf()); + + // typed elements write their class properties first, in declaration order, so only the set of attributes is compared + AssertEquivalent(original, typed, orderSensitive: false); + + var saved = Save(typed); + using var reloaded = DM.Load(saved); + AssertEquivalent(original, reloaded, orderSensitive: false); + + Assert.That(Save(reloaded), Is.EqualTo(saved)); + } + + [Test, TestCaseSource(nameof(VmapFiles))] + public void KeyValues2_Untyped(string file) + { + using var original = DM.Load(Resource(file), Datamodel.Codecs.DeferredMode.Disabled); + + using var text = new MemoryStream(); + original.Save(text, "keyvalues2", 4); + + using var reloaded = DM.Load(text.ToArray()); + + FloatTolerance = 1e-9; + try + { + AssertEquivalent(original, reloaded, orderSensitive: true); + } + finally + { + FloatTolerance = 0; + } + + Assert.That(reloaded.PrefixElementId, Is.EqualTo(original.PrefixElementId)); + + using var text2 = new MemoryStream(); + reloaded.Save(text2, "keyvalues2", 4); + Assert.That(text2.ToArray(), Is.EqualTo(text.ToArray())); + } + + [Test] + public void KeyValues2_MatchesReferenceLayout() + { + // tab indentation, one array item per line, inline elements followed by a blank line, + // elements referenced more than once written after the root, as Valve's serializer lays the text out + using var dm = new DM("test", 1); + dm.PrefixElementId = new Guid("00000000-0000-0000-0000-000000000001"); + dm.PrefixAttributes["refs"] = new StringArray(["a", "b"]); + + var root = new Element(dm, "root", new Guid("00000000-0000-0000-0000-000000000002"), "DmeRoot"); + var child = new Element(dm, string.Empty, new Guid("00000000-0000-0000-0000-000000000003"), "DmeChild"); + var shared = new Element(dm, string.Empty, new Guid("00000000-0000-0000-0000-000000000004"), "DmeShared"); + var item = new Element(dm, string.Empty, new Guid("00000000-0000-0000-0000-000000000005"), "DmeItem"); + dm.Root = root; + + child["value"] = 1; + shared["flag"] = true; + root["child"] = child; + root["shared"] = shared; + root["list"] = new ElementArray([shared, item]); + root["empty"] = new IntArray(); + root["nothing"] = null; + + using var text = new MemoryStream(); + dm.Save(text, "keyvalues2", 4); + + var expected = string.Join("\n", + [ + "", + "\"$prefix_element$\"", + "{", + "\t\"id\" \"elementid\" \"00000000-0000-0000-0000-000000000001\"", + "\t\"refs\" \"string_array\" ", + "\t[", + "\t\t\"a\",", + "\t\t\"b\"", + "\t]", + "}", + "\"DmeRoot\"", + "{", + "\t\"id\" \"elementid\" \"00000000-0000-0000-0000-000000000002\"", + "\t\"name\" \"string\" \"root\"", + "\t\"child\" \"DmeChild\"", + "\t{", + "\t\t\"id\" \"elementid\" \"00000000-0000-0000-0000-000000000003\"", + "\t\t\"value\" \"int\" \"1\"", + "\t}", + "", + "\t\"shared\" \"element\" \"00000000-0000-0000-0000-000000000004\"", + "\t\"list\" \"element_array\" ", + "\t[", + "\t\t\"element\" \"00000000-0000-0000-0000-000000000004\",", + "\t\t\"DmeItem\"", + "\t\t{", + "\t\t\t\"id\" \"elementid\" \"00000000-0000-0000-0000-000000000005\"", + "\t\t}", + "\t]", + "\t\"empty\" \"int_array\" ", + "\t[", + "\t]", + "\t\"nothing\" \"element\" \"\"", + "}", + "", + "\"DmeShared\"", + "{", + "\t\"id\" \"elementid\" \"00000000-0000-0000-0000-000000000004\"", + "\t\"flag\" \"bool\" \"1\"", + "}", + "", + "", + ]); + + Assert.That(Datamodel.Datamodel.TextEncoding.GetString(text.ToArray()), Is.EqualTo(expected)); + } + + [Test] + public void KeyValues2_FloatFormat() + { + using var dm = new DM("test", 1); + dm.Root = new Element(dm, "root"); + dm.Root["position"] = new Vector3(-270.11304f, -233.07538f, 562.09106f); + dm.Root["whole"] = 40f; + dm.Root["negative"] = -1f; + + using var text = new MemoryStream(); + dm.Save(text, "keyvalues2", 4); + var lines = Datamodel.Datamodel.TextEncoding.GetString(text.ToArray()).Split('\n'); + + Assert.That(lines, Does.Contain("\t\"position\" \"vector3\" \"-270.1130371094 -233.075378418 562.0910644531\"")); + Assert.That(lines, Does.Contain("\t\"whole\" \"float\" \"40\"")); + Assert.That(lines, Does.Contain("\t\"negative\" \"float\" \"-1\"")); + } + + [Test] + public void Binary_PrefixAttributes() + { + using var dm = new DM("vmap", 29); + dm.PrefixAttributes["map_asset_references"] = new StringArray(["a.vmdl", "b.vmat"]); + dm.PrefixAttributes["thumbnail_format"] = "jpg"; + dm.PrefixAttributes["thumbnail"] = new byte[] { 1, 2, 3 }; + dm.Root = new Element(dm, "root"); + dm.Root["hello"] = "world"; + + using var reloaded = DM.Load(Save(dm)); + + Assert.That((StringArray?)reloaded.PrefixAttributes["map_asset_references"], Is.EqualTo(new[] { "a.vmdl", "b.vmat" })); + Assert.That((string?)reloaded.PrefixAttributes["thumbnail_format"], Is.EqualTo("jpg")); + Assert.That((byte[]?)reloaded.PrefixAttributes["thumbnail"], Is.EqualTo(new byte[] { 1, 2, 3 })); + Assert.That(reloaded.Root!.Get("hello"), Is.EqualTo("world")); + } + + [Test] + public void Typed_PropertyTypeMismatchIsReported() + { + using var dm = new DM("vmap", 29); + var mesh = new CMapMesh(); + + // disableShadows is an int in the file format + var exception = Assert.Throws(() => mesh["disableShadows"] = true); + Assert.That(exception!.Message, Does.Contain("disableShadows")); + } + + static byte[] Save(DM dm) + { + using var ms = new MemoryStream(); + dm.Save(ms, "binary", 9); + return ms.ToArray(); + } + + static void AssertEquivalent(DM expected, DM actual, bool orderSensitive) + { + AssertAttributesEquivalent(expected.PrefixAttributes, actual.PrefixAttributes, "prefix", orderSensitive); + + var expectedElements = expected.AllElements.ToDictionary(e => e.ID); + var actualElements = actual.AllElements.ToDictionary(e => e.ID); + + Assert.That(actualElements.Keys, Is.EquivalentTo(expectedElements.Keys), "element ids"); + Assert.That(actual.Root?.ID, Is.EqualTo(expected.Root?.ID), "root"); + + foreach (var (id, expectedElement) in expectedElements) + { + var actualElement = actualElements[id]; + Assert.That(actualElement.ClassName, Is.EqualTo(expectedElement.ClassName), $"class of {id}"); + Assert.That(actualElement.Name, Is.EqualTo(expectedElement.Name), $"name of {id}"); + Assert.That(actualElement.Stub, Is.EqualTo(expectedElement.Stub), $"stub of {id}"); + + if (!expectedElement.Stub) + { + AssertAttributesEquivalent(expectedElement, actualElement, $"{expectedElement.ClassName} {id}", orderSensitive); + } + } + } + + static void AssertAttributesEquivalent(AttributeList expected, AttributeList actual, string context, bool orderSensitive) + { + var expectedAttributes = expected.GetAllAttributesForSerialization().ToArray(); + var actualAttributes = actual.GetAllAttributesForSerialization().ToArray(); + + var expectedNames = expectedAttributes.Select(a => a.Key); + var actualNames = actualAttributes.Select(a => a.Key); + + if (orderSensitive) + { + Assert.That(actualNames, Is.EqualTo(expectedNames), $"attribute names and order of {context}"); + } + else + { + // a typed element also writes class properties the source lacked, with their default values, like the real datamodel does + Assert.That(actualNames, Is.SupersetOf(expectedNames), $"attribute names of {context}"); + } + + var actualByName = actualAttributes.ToDictionary(a => a.Key, a => a.Value); + + foreach (var (name, expectedValue) in expectedAttributes) + { + AssertValueEquivalent(expectedValue, actualByName[name], $"{context}.{name}"); + } + } + + static void AssertValueEquivalent(object? expected, object? actual, string context) + { + if (expected is null || actual is null) + { + Assert.That(actual, Is.EqualTo(expected), context); + return; + } + + switch (expected) + { + case Element expectedElement: + Assert.That(actual, Is.InstanceOf(), $"type of {context}"); + Assert.That(((Element)actual).ID, Is.EqualTo(expectedElement.ID), context); + break; + case byte[] expectedBytes: + Assert.That(actual, Is.EqualTo(expectedBytes), context); + break; + case IList expectedList: + Assert.That(actual.GetType(), Is.EqualTo(expected.GetType()), $"type of {context}"); + var actualList = (IList)actual; + Assert.That(actualList.Count, Is.EqualTo(expectedList.Count), $"count of {context}"); + for (var i = 0; i < expectedList.Count; i++) + { + AssertValueEquivalent(expectedList[i], actualList[i], $"{context}[{i}]"); + } + break; + default: + Assert.That(actual.GetType(), Is.EqualTo(expected.GetType()), $"type of {context}"); + + if (FloatTolerance > 0 && TryGetComponents(expected, out var expectedComponents) && TryGetComponents(actual, out var actualComponents)) + { + Assert.That(actualComponents, Is.EqualTo(expectedComponents).Within(FloatTolerance), context); + break; + } + + Assert.That(actual, Is.EqualTo(expected), context); + break; + } + } + + // keyvalues2 prints floats with ten decimals, so values that small lose precision in that encoding + static double FloatTolerance; + + static bool TryGetComponents(object value, out float[] components) + { + components = value switch + { + float f => [f], + Vector2 v => [v.X, v.Y], + Vector3 v => [v.X, v.Y, v.Z], + Vector4 v => [v.X, v.Y, v.Z, v.W], + Quaternion q => [q.X, q.Y, q.Z, q.W], + QAngle a => [a.Pitch, a.Yaw, a.Roll], + _ => [], + }; + + return components.Length > 0; + } + } +} From 15d7a542846c9c13e871d4b128aec03cc5ef95cc Mon Sep 17 00:00:00 2001 From: Angel Date: Fri, 4 Sep 2026 11:56:23 +0200 Subject: [PATCH 13/13] Version 1.0-beta --- Datamodel.NET/Datamodel.NET.csproj | 2 +- README.md | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/Datamodel.NET/Datamodel.NET.csproj b/Datamodel.NET/Datamodel.NET.csproj index 3414567..48ce6e3 100644 --- a/Datamodel.NET/Datamodel.NET.csproj +++ b/Datamodel.NET/Datamodel.NET.csproj @@ -4,7 +4,7 @@ Library Datamodel KeyValues2 - 0.10 + 1.0-beta enable MIT README.md diff --git a/README.md b/README.md index 2ca213f..3f549c5 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,25 @@ class CMapRootElement : Element * Binary codec supports just-in-time attribute loading * Write your own codecs with the `ICodec` interface * Serialize and deserialize support for Datamodel.Element subclasses +* Prefix attributes (such as the `map_asset_references` of a vmap) survive a load and save cycle in both encodings +* Output laid out like Valve's own serializers: `binary` 9 stores the prefix attributes as an element right after the root, `keyvalues2` uses tab indentation and one array item per line + +## Typed elements + +`Datamodel.Load` gives every element whose class name matches a subclass of `Element` in the namespace of `T` that subclass. +Elements with no matching class are loaded as plain `Element`s. + +How the classes are found: + +* The `KeyValues2.ElementFactoryGenerator` source generator emits an `ElementFactory` into every assembly that references this package. +* Loading asks those factories, the one in the assembly of `T` first. No reflection over types happens at load time. + +How a subclass maps onto the file: + +* Every public property is an attribute. The attribute name is the property name, adjusted by `[LowercaseProperties]`, `[CamelCaseProperties]` or `[DMProperty]`. +* Attributes of the file that no property claims are kept as plain attributes and written back unchanged. +* Every property is always written, like in Valve's datamodel. Loading an older file through a class with newer properties adds those with their default values. +* Assigning a file attribute to a property of an incompatible type throws an `InvalidDataException` naming the property, which usually means the class does not match the format. ## Serialization