feat(godot_playfab): Party chat indicators, voice controls, TTS, and network diagnostics - #154
Conversation
…network diagnostics Lands Party spec Phase E. Indicators are polled, never signalled — Party raises no state change when an indicator flips, so titles poll them. Chat indicators - New PlayFabParty.LocalChatIndicator (4 values) and PlayFabParty.ChatIndicator (6 values) enums, mirroring PartyLocalChatControlChatIndicator and PartyChatControlChatIndicator. - PlayFabPartyChat gains get_local_chat_indicator(user), get_chat_indicator(entity_key, user), and the roster helper get_chat_indicators(user); PlayFabPartyChatControl gains get_local_chat_indicator() and get_chat_indicator(). - All getters return safe defaults instead of erroring when there is no local chat control, so they are safe to call every frame. Passing the local player's own entity key to get_chat_indicator() reports TALKING/SILENT, so a single roster loop can drive every row. Local voice controls - set_audio_input_muted_async for push-to-talk. The local mic mute was previously unwrappable — only incoming mute existed. - get/set_audio_render_volume, get/set_audio_encoder_bitrate, and get/set_voice_audio_options. - Polled get_audio_input_state() / get_audio_output_state() so titles can distinguish "no microphone" from "consent denied" instead of silently having no voice. Device state is now cached from the LocalChatAudioInput/OutputChanged state changes instead of only being ERR_PRINTed. Language, transcription, and translation now actually work PlayFabPartyConfig.enable_transcription and enable_translation were bound but inert: the addon never called SetTranscriptionOptions or SetTextChatOptions, so transcription_received was unreachable and translated_text always equalled text. _configure_chat_language_options() now applies them (plus the new PlayFabPartyConfig.language) at chat-control creation, and get/set_language, get/set_transcription_options, and get/set_text_chat_options are exposed directly. Text-to-speech populate_text_to_speech_profiles_async, get_text_to_speech_profiles, get/set_text_to_speech_profile, and synthesize_text_to_speech_async, with a new PlayFabPartyTextToSpeechProfile value type. Profiles are snapshotted because the SDK invalidates PartyTextToSpeechProfile* on the next populate call. Network diagnostics PlayFabPartyNetwork.get_statistics(subset) (lower-snake-case keys matching the 16 NETWORK_STATISTIC_* constants; an empty subset returns all) and get_device_connection_type(peer_id). Bug fixes - send_text_async passed dataBufferCount = 0, nullptr, so PlayFabPartyTextMessageConfig.metadata was silently dropped. It is now serialized into a single PartyDataBuffer and decoded on receipt with object instantiation disabled. - PlayFabPartyChatMessage gains original_text and options, and transcriptions now carry translations. Breaking changes - PlayFabPartyConfig.metadata is removed (it was never read; PlayFabPartyConfig.language replaces the slot). - PlayFabPartyTextMessageConfig.language_code and .translate_to_languages are removed. Party has no per-message language or translation, so those fields could never have worked. Sender language is set_language_async; translation is receiver-side set_text_chat_options_async(TEXT_CHAT_OPTION_TRANSLATE_TO_LOCAL_LANGUAGE). Deliberately out of scope for this phase: endpoint/network shared properties (the native setters are no-ops for the addon's usage), chat-control audio-device selection setters, PartyXbl, and the remaining unhandled state-change types. doc_classes, the C# facades under addons/godot_playfab_csharp/Types/, docs/playfab/plugin.md, spec/gdext-playfab-party.md (Phase E), and the tests/godot/playfab GUT surface/constant/detached-error assertions are updated in this change. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 48b0f6a8-798d-4e79-9e61-e9b5e9084b09
…pper table Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 48b0f6a8-798d-4e79-9e61-e9b5e9084b09
There was a problem hiding this comment.
Pull request overview
This PR advances the godot_playfab Party integration to Phase E, expanding the Godot-facing Party chat surface with polled chat indicators, local voice controls, text-to-speech, and network diagnostics, while also fixing previously inert transcription/translation configuration and text-message metadata delivery.
Changes:
- Add Party chat polling surfaces (indicators + device state), local voice controls, TTS profile APIs, and network diagnostics.
- Fix Party text message metadata transport and enrich received message fields (original text + options), plus ensure transcription/translation settings are actually applied.
- Update tests/spec/docs and C# facade parity, including a new
PlayFabPartyTextToSpeechProfilevalue type.
Reviewed changes
Copilot reviewed 23 out of 23 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/godot/playfab/tests/test_party.gd | Expands API-surface and constant-value assertions for new Party Phase E features and breaking changes. |
| tests/godot/playfab/tests/test_core.gd | Registers the new Party TTS profile type in the PlayFab test host’s class list. |
| spec/gdext-playfab-party.md | Updates Party spec (Phase E shipped), documents new polling/voice/TTS/diagnostics surfaces, and reflects breaking changes. |
| spec/gdext-csharp.md | Updates the C# parity matrix to include PlayFabPartyTextToSpeechProfile. |
| docs/playfab/plugin.md | Updates user-facing PlayFab docs overview to mention the expanded Party voice/diagnostics surface. |
| addons/godot_playfab/src/register_types.cpp | Registers the new PlayFabPartyTextToSpeechProfile class with Godot. |
| addons/godot_playfab/src/playfab_party.h | Adds new enums/APIs and new value type; removes deprecated config fields; extends message fields. |
| addons/godot_playfab/src/playfab_party.cpp | Implements new Party chat control APIs (polling + setters), TTS profile snapshotting, network diagnostics, and metadata send/receive fixes. |
| addons/godot_playfab/doc_classes/PlayFabPartyTextToSpeechProfile.xml | Adds new class documentation for the TTS profile value type. |
| addons/godot_playfab/doc_classes/PlayFabPartyTextMessageConfig.xml | Removes per-message language/translation docs; documents metadata transport behavior. |
| addons/godot_playfab/doc_classes/PlayFabPartyNetwork.xml | Documents new network diagnostics methods (get_statistics, get_device_connection_type). |
| addons/godot_playfab/doc_classes/PlayFabPartyConfig.xml | Replaces deprecated metadata with language and clarifies transcription/translation behavior. |
| addons/godot_playfab/doc_classes/PlayFabPartyChatMessage.xml | Documents new original_text and options fields on received messages. |
| addons/godot_playfab/doc_classes/PlayFabPartyChatControl.xml | Documents new chat-control polling state and local voice/TTS controls. |
| addons/godot_playfab/doc_classes/PlayFabPartyChat.xml | Documents new Party chat polling, voice controls, translation/transcription, and TTS entry points. |
| addons/godot_playfab/doc_classes/PlayFabParty.xml | Adds enums/constants for indicators, audio device state, transcription/text-chat options, message options, TTS, and diagnostics. |
| addons/godot_playfab_csharp/Types/PlayFabPartyTextToSpeechProfile.cs | Adds C# wrapper for the new Party TTS profile value type. |
| addons/godot_playfab_csharp/Types/PlayFabPartyTextMessageConfig.cs | Removes per-message language/translation accessors, keeping metadata only. |
| addons/godot_playfab_csharp/Types/PlayFabPartyNetwork.cs | Adds C# wrappers for network diagnostics APIs. |
| addons/godot_playfab_csharp/Types/PlayFabPartyConfig.cs | Replaces Metadata with Language in the C# config wrapper. |
| addons/godot_playfab_csharp/Types/PlayFabPartyChatMessage.cs | Adds C# accessors for OriginalText and Options. |
| addons/godot_playfab_csharp/Types/PlayFabPartyChatControl.cs | Adds C# wrappers for new polling state, voice controls, and TTS control APIs. |
| addons/godot_playfab_csharp/Types/PlayFabPartyChat.cs | Adds C# wrappers for Party chat polling, voice controls, language/options, and TTS APIs. |
Suppressed comments (1)
addons/godot_playfab/doc_classes/PlayFabPartyChatMessage.xml:34
- The original_text member description says it is empty when no filtering occurred, but the implementation sets original_text to text when Party doesn't supply originalChatText. This should be documented as an untranslated-source field (and equal to text when not translated), with filtering indicated by options.
<member name="original_text" type="String" setter="" getter="get_original_text">The unfiltered message text as sent, when the service applied offensive-term filtering. Empty when no filtering occurred.</member>
<member name="options" type="int" setter="" getter="get_options">Bitmask describing service-applied filtering. See [enum PlayFabParty.ChatMessageOptions].</member>
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…d chat-message doc drift - Restore the collapsed PlayFabPartyNetwork::leave_async() function header. - Correct spec: PlayFabPartyChatMessage.options carries CHAT_MESSAGE_OPTION_* (Party's PartyChatTextReceivedOptions filtering flags), not TEXT_CHAT_OPTION_* (receiver-side text chat configuration). - Correct original_text docs in both doc_classes and spec. It is populated from Party's originalChatText, which is always the unfiltered source text and is set equal to chatText when filtering is disabled or was not needed -- it is NOT empty in that case. Titles must inspect options rather than test for an empty string to detect filtering. It is empty only for transcriptions, which omit the field. - Clarify the metadata decode comment: bytes_to_var() is itself the objects-disabled API (there is no allow_objects parameter in godot-cpp); the object-allowing variant is the separate bytes_to_var_with_objects(). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 48b0f6a8-798d-4e79-9e61-e9b5e9084b09
|
Thanks — three of four applied in 09c4f04. Fixed
Not applied
Validation: debug build clean; full non-live |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 23 out of 23 changed files in this pull request and generated no new comments.
Suppressed comments (2)
addons/godot_playfab/src/playfab_party.cpp:352
PlayFabPartyChatMessage.original_textis documented as empty for transcriptions, butset_values()currently forcesoriginal_textto fall back totextwheneverp_original_textis empty. Since the transcription path passes no original text, transcriptions will incorrectly reportoriginal_text == textinstead of empty.
m_original_text = p_original_text.is_empty() ? p_text : p_original_text;
addons/godot_playfab/src/playfab_party.cpp:641
PlayFabPartyChatControl.set_audio_input_muted_async()reportsparty_chat_permission_failedwhen the caller doesn't have a valid connected local chat control. This is misleading (it's not a permissions failure) and is inconsistent with other local chat-control setters in this file that useparty_chat_control_create_failedfor the same precondition.
Signal PlayFabPartyChatControl::set_audio_input_muted_async(bool p_muted) {
if (m_owner == nullptr || m_native_handle == nullptr || !m_local) {
return detached_error_signal(E_NOT_VALID_STATE, PARTY_CHAT_PERMISSION_FAILED,
"PlayFabPartyChatControl.set_audio_input_muted_async requires a local chat control.");
}
Lands Party spec Phase E: chat indicators, local voice controls, working transcription/translation, text-to-speech, and network diagnostics for
godot_playfab.This work was written but never committed — it had been sitting as uncommitted edits in an unrelated worktree. This PR moves it onto its own branch off
mainwith no functional changes.Chat indicators
Indicators are polled, never signalled — Party raises no state change when an indicator flips, so titles poll them. All getters return safe defaults instead of erroring when there is no local chat control, so they are safe to call every frame.
New enums:
PlayFabParty.LocalChatIndicator(4 values) andPlayFabParty.ChatIndicator(6 values), mirroringPartyLocalChatControlChatIndicator/PartyChatControlChatIndicator.PlayFabPartyChatControlgains the same two getters.Local voice controls
The local mic mute was previously unwrappable — only incoming mute existed, so push-to-talk was impossible.
Also adds
is_audio_input_muted,get_audio_render_volume,get_audio_encoder_bitrate,get/set_voice_audio_options, andget_audio_output_state. Audio-device state is now cached from theLocalChatAudioInput/OutputChangedstate changes instead of only beingERR_PRINTed.Language / transcription / translation now actually work
PlayFabPartyConfig.enable_transcriptionandenable_translationwere bound but inert — the addon never calledSetTranscriptionOptionsorSetTextChatOptions, sotranscription_receivedwas unreachable andtranslated_textalways equalledtext._configure_chat_language_options()applies them at chat-control creation, andget_language/set_language_async,get_transcription_options/set_transcription_options_async, andget_text_chat_options/set_text_chat_options_asyncare exposed directly.Text-to-speech
New
PlayFabPartyTextToSpeechProfilevalue type (identifier,name,language_code,gender). Profiles are snapshotted because the SDK invalidatesPartyTextToSpeechProfile*on the next populate call.Network diagnostics
Keys are lower-snake-case and match the 16
NETWORK_STATISTIC_*constants.Bug fixes
send_text_asyncpasseddataBufferCount = 0, nullptr, soPlayFabPartyTextMessageConfig.metadatawas silently dropped. It is now serialized into a singlePartyDataBufferand decoded on receipt with object instantiation disabled.PlayFabPartyChatMessagegainsoriginal_textandoptions, and transcriptions now carry translations.PlayFabPartyConfig.metadatais removed — it was never read.PlayFabPartyConfig.languagereplaces the slot.PlayFabPartyTextMessageConfig.language_codeand.translate_to_languagesare removed. Party has no per-message language or translation, so these fields could never have worked.Migration:
No in-repo consumer referenced any of the removed fields (verified across samples, tutorials, the MP test client, and the C# facades).
Out of scope for this phase
Endpoint/network shared properties (the native setters are no-ops for the addon's usage), chat-control audio-device selection setters, PartyXbl, and the remaining unhandled state-change types.
Validation
cmake --preset default+cmake --build build --preset debug— clean, addon mirrored to all sample/test hosts.tools\check_gd_scripts_headless.ps1) — passed.tools\run_all_tests.ps1), Godot 4.6.2:tests\godot\gdk: 330 tests, 3092/3092 asserts, 0 failedtests\godot\playfab: 84 tests, 1932/1932 asserts, 0 failedtests\godot\gameinput: 60 tests, 10534/10534 asserts, 0 failedtools\run_csharp_tests.ps1): 107 passed, 0 failed — confirms every newdoc_classesmethod/member has a managed wrapper, including the newPlayFabPartyTextToSpeechProfile.-Live, no-AllowLiveWrites. The PlayFab MP orchestrator stage was skipped. Voice capture, TTS synthesis, transcription, and translation are inherently live-service paths and have not been exercised against a real title — a reviewer with a sandbox title should runrun_all_tests.ps1 -Livebefore merge.Docs / spec / tests updated in this change
addons/godot_playfab/doc_classes/*.xml(incl. newPlayFabPartyTextToSpeechProfile.xml), the C# facades underaddons/godot_playfab_csharp/Types/,docs/playfab/plugin.md,spec/gdext-playfab-party.md(Phase E marked shipped),spec/gdext-csharp.md, and thetests/godot/playfabGUT surface / constant-value / detached-error assertions.