void XblMultiplayerSession::SerializeSessionConstants()

in Source/Services/Multiplayer/multiplayer_session.cpp [1625:1820]


void XblMultiplayerSession::SerializeSessionConstants(_Out_ JsonValue& json, _In_ JsonDocument::AllocatorType& allocator)
{
    if (!m_writeConstants)
    {
        return;
    }

    json.SetObject();

    JsonValue systemJson(rapidjson::kObjectType);
    systemJson.AddMember("version", MULTIPLAYER_SESSION_VERSION, allocator);
    if (m_sessionConstants.MaxMembersInSession > 0)
    {
        systemJson.AddMember("maxMembersCount", m_sessionConstants.MaxMembersInSession, allocator);
    }

    JsonValue systemCapabilitiesJson(rapidjson::kObjectType);
    if (m_sessionConstants.SessionCapabilities.Connectivity)
    {
        systemCapabilitiesJson.AddMember("connectivity", true, allocator);
    }

    if (m_sessionConstants.SessionCapabilities.SuppressPresenceActivityCheck)
    {
        systemCapabilitiesJson.AddMember("suppressPresenceActivityCheck", true, allocator);
    }

    if (m_sessionConstants.SessionCapabilities.Gameplay)
    {
        systemCapabilitiesJson.AddMember("gameplay", true, allocator);
    }

    if (m_sessionConstants.SessionCapabilities.Large)
    {
        systemCapabilitiesJson.AddMember("large", true, allocator);
    }

    if (m_sessionConstants.SessionCapabilities.UserAuthorizationStyle)
    {
        systemCapabilitiesJson.AddMember("userAuthorizationStyle", true, allocator);
    }

    if (m_sessionConstants.SessionCapabilities.ConnectionRequiredForActiveMembers)
    {
        systemCapabilitiesJson.AddMember("connectionRequiredForActiveMembers", true, allocator);
    }

    if (m_sessionConstants.SessionCapabilities.Crossplay)
    {
        systemCapabilitiesJson.AddMember("crossPlay", true, allocator);
    }
    
    if (m_sessionConstants.SessionCapabilities.Searchable)
    {
        systemCapabilitiesJson.AddMember("searchable", true, allocator);
    }

    if (m_sessionConstants.SessionCapabilities.HasOwners)
    {
        systemCapabilitiesJson.AddMember("hasOwners", true, allocator);
    }

    if (!systemCapabilitiesJson.IsNull() && !systemCapabilitiesJson.ObjectEmpty())
    {
        systemJson.AddMember("capabilities", systemCapabilitiesJson, allocator);
    }

    if (m_sessionConstants.Visibility != XblMultiplayerSessionVisibility::Any && m_sessionConstants.Visibility != XblMultiplayerSessionVisibility::Unknown)
    {
        auto visibilityString = Serializers::StringFromMultiplayerSessionVisibility(m_sessionConstants.Visibility);
        systemJson.AddMember("visibility", JsonValue(visibilityString.c_str(), allocator).Move(), allocator);
    }

    if (m_sessionConstants.InitiatorXuids != nullptr && m_sessionConstants.InitiatorXuidsCount > 0)
    {
        std::sort(m_sessionConstants.InitiatorXuids, m_sessionConstants.InitiatorXuids + m_sessionConstants.InitiatorXuidsCount);
        JsonValue jsonArray(rapidjson::kArrayType);
        for (uint32_t i = 0; i < m_sessionConstants.InitiatorXuidsCount; ++i)
        {
            jsonArray.PushBack(JsonValue(utils::uint64_to_internal_string(m_sessionConstants.InitiatorXuids[i]).c_str(), allocator).Move(), allocator);
        }
        systemJson.AddMember("initiators", jsonArray, allocator);
    }

    if (m_writeTimeouts)
    {
        JsonValue reservedRemovalTimeoutJson;
        JsonUtils::SerializeUInt52ToJson(m_sessionConstants.MemberReservedTimeout, reservedRemovalTimeoutJson);
        systemJson.AddMember("reservedRemovalTimeout", reservedRemovalTimeoutJson, allocator);

        JsonValue inactiveRemovalTimeoutJson;
        JsonUtils::SerializeUInt52ToJson(m_sessionConstants.MemberInactiveTimeout, inactiveRemovalTimeoutJson);
        systemJson.AddMember("inactiveRemovalTimeout", inactiveRemovalTimeoutJson, allocator);
        
        JsonValue readyRemovalTimeoutJson;
        JsonUtils::SerializeUInt52ToJson(m_sessionConstants.MemberReadyTimeout, readyRemovalTimeoutJson);
        systemJson.AddMember("readyRemovalTimeout", readyRemovalTimeoutJson, allocator);

        JsonValue sessionEmptyTimeoutJson;
        JsonUtils::SerializeUInt52ToJson(m_sessionConstants.SessionEmptyTimeout, sessionEmptyTimeoutJson);
        systemJson.AddMember("sessionEmptyTimeout", sessionEmptyTimeoutJson, allocator);
    }

    if (m_writeQosConnectivityMetrics)
    {
        JsonValue systemMetricsJson(rapidjson::kObjectType);
        systemMetricsJson.AddMember("latency", m_sessionConstants.EnableMetricsLatency, allocator);
        systemMetricsJson.AddMember("bandwidthDown", m_sessionConstants.EnableMetricsBandwidthDown, allocator);
        systemMetricsJson.AddMember("bandwidthUp", m_sessionConstants.EnableMetricsBandwidthUp, allocator);
        systemMetricsJson.AddMember("custom", m_sessionConstants.EnableMetricsCustom, allocator);
        systemJson.AddMember("metrics", systemMetricsJson, allocator);
    }

    if (m_writeMemberInitialization)
    {
        JsonValue memberInitializationJson{ rapidjson::kObjectType };

        JsonValue joinTimeoutJson;
        JsonUtils::SerializeUInt52ToJson(m_sessionConstants.MemberInitialization->JoinTimeout, joinTimeoutJson);
        memberInitializationJson.AddMember("joinTimeout", joinTimeoutJson, allocator);

        JsonValue measurementTimeoutJson;
        JsonUtils::SerializeUInt52ToJson(m_sessionConstants.MemberInitialization->MeasurementTimeout, measurementTimeoutJson);
        memberInitializationJson.AddMember("measurementTimeout", measurementTimeoutJson, allocator);

        if (m_sessionConstants.MemberInitialization->ExternalEvaluation)
        {
            JsonValue evaluationTimeoutJson;
            JsonUtils::SerializeUInt52ToJson(m_sessionConstants.MemberInitialization->EvaluationTimeout, evaluationTimeoutJson);
            memberInitializationJson.AddMember("evaluationTimeout", evaluationTimeoutJson, allocator);
        }

        memberInitializationJson.AddMember("externalEvaluation", m_sessionConstants.MemberInitialization->ExternalEvaluation, allocator);
        memberInitializationJson.AddMember("membersNeededToStart", m_sessionConstants.MemberInitialization->MembersNeededToStart, allocator);

        systemJson.AddMember("memberInitialization", memberInitializationJson, allocator);
    }

    if (m_writePeerToPeerRequirements)
    {
        JsonValue peerToPeerRequirementsJson(rapidjson::kObjectType);

        JsonValue latencyMaxJson;
        JsonUtils::SerializeUInt52ToJson(m_sessionConstants.PeerToPeerRequirements.LatencyMaximum, latencyMaxJson);
        peerToPeerRequirementsJson.AddMember("latencyMaximum", latencyMaxJson, allocator);

        peerToPeerRequirementsJson.AddMember("bandwidthMinimum", m_sessionConstants.PeerToPeerRequirements.BandwidthMinimumInKbps, allocator);
        systemJson.AddMember("peerToPeerRequirements", peerToPeerRequirementsJson, allocator);
    }

    if (m_writePeerToHostRequirements)
    {
        JsonValue peerToHostRequirementsJson(rapidjson::kObjectType);

        JsonValue latencyMaxJson;
        JsonUtils::SerializeUInt52ToJson(m_sessionConstants.PeerToHostRequirements.LatencyMaximum, latencyMaxJson);
        peerToHostRequirementsJson.AddMember("latencyMaximum",latencyMaxJson, allocator);

        peerToHostRequirementsJson.AddMember("bandwidthDownMinimum", m_sessionConstants.PeerToHostRequirements.BandwidthDownMinimumInKbps, allocator);
        peerToHostRequirementsJson.AddMember("bandwidthUpMinimum", m_sessionConstants.PeerToHostRequirements.BandwidthUpMinimumInKbps, allocator);
        peerToHostRequirementsJson.AddMember(
            "hostSelectionMetric", 
            JsonValue(XblMultiplayerSession::ConvertMultiplayerHostSelectionMetricToString(m_sessionConstants.PeerToHostRequirements.HostSelectionMetric).c_str(), allocator).Move(), 
            allocator
        );

        systemJson.AddMember("peerToHostRequirements", peerToHostRequirementsJson, allocator);
    }

    if (m_writeMeasurementServerAddresses)
    {
        JsonDocument measurementServerAddressesJson;
        measurementServerAddressesJson.Parse(m_sessionConstants.MeasurementServerAddressesJson);
        systemJson.AddMember("measurementServerAddresses", measurementServerAddressesJson, allocator);
    }

    if (m_sessionConstants.SessionCloudComputePackageConstantsJson != nullptr && m_sessionConstants.SessionCloudComputePackageConstantsJson[0] != 0)
    {
        JsonDocument cloudComputePackage{ &allocator };
        cloudComputePackage.Parse(m_sessionConstants.SessionCloudComputePackageConstantsJson);
        systemJson.AddMember("cloudComputePackage", cloudComputePackage, allocator);
    }

    json.AddMember("system", systemJson, allocator);

    if (m_sessionConstants.CustomJson != nullptr && m_sessionConstants.CustomJson[0] != 0)
    {
        JsonDocument customJson{ &allocator };
        customJson.Parse(m_sessionConstants.CustomJson);
        json.AddMember("custom", customJson, allocator);
    }
    else
    {
        json.AddMember("custom", JsonValue(rapidjson::kObjectType), allocator);
    }
}