Orientation for a coding agent (and for a human who has just cloned this) changing the plugin
itself. If you are writing game code that uses PsData, read
docs/ai-guide.md instead.
PsData is a reactive data model for Unreal Engine: game data declared as C++ classes with macros
(DPROP, DARRAY, DMAP, DLINK), with change events that bubble up the tree, typed links between
branches, JSON/binary serialization, DataTable import, content hashing and generated Blueprint
nodes. Source plugin, MIT, UE 5.6–5.8 verified.
Tools/test.sh <engine-root> # build the editor target in a throwaway host, run PsData.* tests
Tools/test.sh <engine-root> --game # also the monolithic Game target — do this before a releaseThe script prints one line per test and exits non-zero on any build error or failed test. It also
prints every compiler warning located in the plugin: a plugin warning is a bug, not noise —
deprecations become errors one engine later. Details, Windows steps and the coverage table:
docs/dev/testing.md.
If more than one engine is installed, run the script on the newest and the oldest one you support; version guards that are only compiled on one side rot silently.
PsData.uplugin
Source/
PsData/ Runtime module — everything a game links
Public/PsDataAPI.h the macros (DPROP, DMETA, DLINK, MAKE_TABLE_STRUCT, ...) and TDProp/TDLink
Public/PsData.h UPsData: tree, events, serialize entry points
Public/PsDataCore.h FDataReflection: field registry, compile at PostEngineInit
Public/PsDataProperty.h TDataProperty<T>: storage, SetValue, event storage
Public/PsDataLink.h link resolution and caching
Public/PsDataDefines.h PSDATA_ENGINE_AT_LEAST, PSDATA_SHRINK, FProperty helpers
Public/Collection/ array and map proxies (C++ and Blueprint)
Public/Serialize/ JSON, fast JSON, binary, optimized binary, struct, DataTable, schema
Public/Types/ one file pair per supported value type
Public/PsNetworkData.h UPsNetworkData replication
PsDataEditor/ UncookedOnly — Blueprint nodes, pin factory, details customizations
Tests/PsDataTests/ a separate plugin: the automation suite and its test model. Nested inside
PsData it is never discovered, so game projects never get its classes;
Tools/test.sh installs it next to PsData in the host project
Config/ CoreRedirects for pre-2019 module names
Resources/Icon128.png plugin browser icon
Tools/test.sh build + test runner
Tools/gen_model_diagram.py regenerates docs/assets/model-*.svg (README diagram)
docs/ user documentation; docs/dev/ is for contributors; docs/assets/ images,
docs/assets/brand/ logo notes, concept sheet, social preview
- Engine-version code goes through
PSDATA_ENGINE_AT_LEAST(Major, Minor)(PsDataDefines.h). Never testENGINE_MINOR_VERSIONalone. Keep the older branch compiling: the plugin is used on more than one engine at a time. - No
boolshrink arguments.RemoveAt,Pop,SetNumtakePSDATA_NO_SHRINKorPSDATA_SHRINK(bAllow); thebooloverloads are gone in 5.8. - No direct
FJsonObject::Valuesaccess by key. Keys areFStringbefore 5.8 andUE::FSharedStringsince. UseSetField/TryGetField, andFString(*Pair.Key)when iterating. - Preserve line endings. Some files are CRLF (
PsDataDefines.h,PsDataStruct.h,PsDataLink.h,PsDataUtils.h,PsNetworkData.*,PsDataFixedPoint.*, ...), most are LF. Edit in place; do not normalize a file you are not otherwise rewriting. - Format with the repo's
Source/.clang-format(tabs, Allman braces, no column limit).clang-format --style=file:Source/.clang-format -i <file>on files you touch. - The wire format is a contract. Field keys, enum-by-name, binary token values and the
fast-JSON layout are read back by saved games and live servers. A change there needs a
migration story and a
CHANGELOG.mdentry. - Game thread only. The event scope guard and delegate tables are unsynchronized statics.
Don't introduce PsData calls on other threads;
DataSerializeAsyncconverts an already-taken snapshot off-thread and is the pattern to copy. - A fix comes with a test, and the test has been seen to fail. Add it to
Tests/PsDataTests(one file per area), revert the fix, watch it fail, restore. Name testsPsData.<Area>.<Case>, and never give a test the name of another test's group (PsData.Serializationnext toPsData.Serialization.Translate): the shorter one silently stops running. Check the count. - Docs are part of the change. Public API or behaviour changes update the matching page in
docs/and, if user-visible,CHANGELOG.md. Code samples in docs must compile against the plugin — the safest source for a sample is a test. In Markdown code blocks indent with four spaces (GitHub draws a tab eight wide), put comments above the line they explain —/** */over a property,//over a statement — and keep lines within 90 characters, which is what GitHub shows without a scrollbar. - New source files start with the repository's copyright line
(
// Copyright 2015-2026 Pushkin Studio. All Rights Reserved.) like their neighbours.
| Page | For |
|---|---|
README.md |
front page |
docs/getting-started.md |
install to first saved model |
docs/model.md |
macros, meta, types, tree, enforced rules |
docs/events.md |
event semantics |
docs/serialization.md |
formats, patching, hashing, DataTables, replication |
docs/blueprints.md |
generated nodes |
docs/cookbook.md |
production patterns |
docs/ai-guide.md |
agents using the plugin |
docs/dev/testing.md |
building and testing the plugin |
llms.txt |
index for LLM tools |
CHANGELOG.md |
what changed per version |