public void Serialize <TDoc, TCursor>(IO.TagElementStream <TDoc, TCursor, string> s)
            where TDoc : class
            where TCursor : class
        {
            using (s.EnterOwnerBookmark(this))
            {
                s.StreamAttribute("version", ref Version);

                using (s.EnterCursorBookmark("Limits"))
                    Limits.Serialize(s);

                using (var bm = s.EnterCursorBookmarkOpt("SingleEncodings", SingleEncodings, Predicates.HasItems)) if (bm.IsNotNull)
                    {
                        s.StreamableElements("Traits", SingleEncodings);
                    }

                using (s.EnterCursorBookmark("EnumTypes"))
                    s.StreamableElements("Type", Enums, e => !e.IsCodeEnum);

                if (s.IsReading)
                {
                    SingleEncodings.Sort((x, y) => string.CompareOrdinal(x.Name, y.Name));
                    Enums.Sort((x, y) => string.CompareOrdinal(x.Name, y.Name));
                }

                using (s.EnterCursorBookmark("VariableSets"))
                    s.StreamableElements("Set", VariableSets,
                                         "type", MegaloScriptProtoVariableSet.StreamSetType);
                using (s.EnterCursorBookmark("ValueTypes"))
                    s.StreamElements("Type", ValueTypes, this, SerializeValueType);

                if (s.IsReading)
                {
                    ValueTypes.ForEach(type => NameToValueType.Add(ValueTypeNames[type.NameIndex], type));
                }

                using (s.EnterCursorBookmark("VariableReferenceTypes"))
                    s.StreamableElements("Type", VariableRefTypes,
                                         "type", MegaloScriptProtoVariableReference.StreamType);

                using (s.EnterCursorBookmark("Conditions"))
                    s.StreamableElements("Condition", Conditions);
                using (s.EnterCursorBookmark("ActionTemplates"))
                    s.StreamableElements("Template", ActionTemplates);
                using (s.EnterCursorBookmark("Actions"))
                    s.StreamableElements("Action", Actions);

                if (s.IsReading)
                {
                    mConditionTypeBitLength = Bits.GetMaxEnumBits(Conditions.Count);
                    mActionTypeBitLength    = Bits.GetMaxEnumBits(Actions.Count);

                    Conditions.ForEach(cond => NameToConditionMap.Add(cond.Name, cond));
                    Actions.ForEach(action => NameToActionMap.Add(action.Name, action));

                    TeamDesignatorValueType  = NameToValueType["TeamDesignator"];
                    ObjectTypeIndexValueType = NameToValueType["ObjectTypeIndex"];

                    ForEachAction = NameToActionMap["for_each"];
                    if (Limits.SupportsVirtualTriggers)
                    {
                        BeginAction = NameToActionMap["begin"];
                    }

                    ObjectReferenceWithPlayerVarIndex.Initialize(this);
                }
            }
        }