KeyValues2 2.0.0-beta
dotnet add package KeyValues2 --version 2.0.0-beta
NuGet\Install-Package KeyValues2 -Version 2.0.0-beta
<PackageReference Include="KeyValues2" Version="2.0.0-beta" />
<PackageVersion Include="KeyValues2" Version="2.0.0-beta" />
<PackageReference Include="KeyValues2" />
paket add KeyValues2 --version 2.0.0-beta
#r "nuget: KeyValues2, 2.0.0-beta"
#:package KeyValues2@2.0.0-beta
#addin nuget:?package=KeyValues2&version=2.0.0-beta&prerelease
#tool nuget:?package=KeyValues2&version=2.0.0-beta&prerelease
Datamodel.NET is a library which implements the Datamodel structure and Datamodel Exchange (DMX) file format.
Datamodel is a strongly-typed generic data structure designed by Valve Corporation. It is primarily used as a developer storage format for meshes, animations, and maps.
Usage
dotnet add package KeyValues2
using Datamodel;
// Load a file with unknown layout
using var dm = Datamodel.Load("my_file.dmx");
var element = dm.Root;
var value = element.Get<string>("my_property");
// Load a file with a known layout
using var map = Datamodel.Load<CMapRootElement>("fy_pool.vmap");
var root = (CMapRootElement)map.Root;
Debug.Assert(root.IsPrefab == false);
// Layout definition
// Full implementation can be found here:
// https://github.com/ValveResourceFormat/Datamodel.NET/blob/master/Tests/ValveMap.cs
[LowercaseProperties]
class CMapRootElement : Element
{
public bool IsPrefab { get; set; }
public int EditorBuild { get; set; } = 8600;
public int EditorVersion { get; set; } = 400;
}
Features
- Support for all known versions of Valve's
binaryandkeyvalues2DMX encodings - Inline documentation
- Binary codec supports just-in-time attribute loading
- Write your own codecs with the
ICodecinterface - Serialize and deserialize support for Datamodel.Element subclasses
- Prefix attributes (such as the
map_asset_referencesof a vmap) survive a load and save cycle in both encodings - Output laid out like Valve's own serializers:
binary9 stores the prefix attributes as an element right after the root,keyvalues2uses tab indentation and one array item per line
Typed elements
Datamodel.Load<T> 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 Elements.
How the classes are found:
- A source generator, shipped inside the package, emits an
ElementFactoryinto every assembly that declaresElementsubclasses. It constructs the classes by name, lists their properties, and registers itself when the assembly is initialised. - Loading asks the registered factories, the one in the assembly of
Tfirst. Pass aLoadOptionsto pick another namespace or factory. - The library uses no reflection and is compatible with trimming and Native AOT. Properties with
initor non-public setters are assigned throughUnsafeAccessor, so the classes need no special shape.
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
InvalidDataExceptionnaming the property, which usually means the class does not match the format. - A class must be
internalorpublicfor the generated factory to see it. A private nested class is loaded as a plainElementand the generator warns about it (DMX002).
Serialization
var HelloWorld = new Datamodel.Datamodel("helloworld", 1); // must provide a format name (can be anything) and version
HelloWorld.Root = new Datamodel.Element(HelloWorld, "my_root");
HelloWorld.Root["Hello"] = "World"; // any supported attribute type can be assigned
var MyString = HelloWorld.Root.Get<string>("Hello");
HelloWorld.Save("hello world.dmx", "keyvalues2", 1); // must provide an encoding name and version
<--! dmx encoding keyvalues2 1 format helloworld 1>
{
"Hello" "string" "World"
}
Attributes
The following .NET types are supported as Datamodel attributes:
intfloatboolstringbytebyte[]Vector2Vector3Vector4/QuaternionMatrix4x4ulongSystem.TimeSpan
Additionally, the following Datamodel.NET types are supported:
Element(a named collection of attributes)QAngle
IList<T> collections of the above types are also supported. (This can be a bit confusing given that both byte and byte[] are valid attribute types; use the ByteArray type if you run into trouble.)
License
Datamodel.NET is licensed under the MIT License.
The sample .dmx and .vmap files under Tests/Resources are derived from Valve
Corporation game content and are included solely as test fixtures. They are not covered by the MIT
license above and remain the property of Valve Corporation. They are not distributed in the NuGet package.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- No dependencies.
NuGet packages (1)
Showing the top 1 NuGet packages that depend on KeyValues2:
| Package | Downloads |
|---|---|
|
ValveResourceFormat
Parser, decompiler, and exporter for Valve's Source 2 resource file formats. Supports models, textures, materials, maps, particles, and more. |
GitHub repositories (1)
Showing the top 1 popular GitHub repositories that depend on KeyValues2:
| Repository | Stars |
|---|---|
|
ValveResourceFormat/ValveResourceFormat
Source 2 Viewer is an all-in-one tool to browse VPK archives, view, extract, and decompile Source 2 assets, including maps, models, materials, textures, sounds, and more.
|
| Version | Downloads | Last Updated |
|---|---|---|
| 2.0.0-beta | 2 | 9/8/2026 |
| 1.0.0 | 138 | 9/7/2026 |
| 0.10.0 | 117 | 8/24/2026 |
| 0.9.0 | 108 | 8/22/2026 |
| 0.9.0-beta | 257 | 6/5/2025 |
| 0.8.0 | 28,576 | 5/25/2025 |
| 0.7.0 | 231 | 5/24/2025 |
| 0.5.0 | 5,292 | 9/25/2024 |
| 0.5.0-beta | 6,672 | 3/11/2024 |
| 0.4.0 | 1,202 | 1/22/2024 |
| 0.3.0 | 6,942 | 6/30/2023 |
| 0.2.0 | 373 | 5/3/2023 |