저장된 게임

이 가이드에서는 C++ SDK에서 Google Play 게임즈 서비스에서 제공하는 스냅샷 API를 사용하여 저장된 게임을 구현하는 방법을 보여줍니다. API는 PgsSnapshotsClient에서 확인할 수 있습니다.

시작하기 전에

스냅샷 클라이언트 가져오기

Snapshots API를 사용하려면 먼저 게임에서 PgsSnapshotsClient 핸들을 가져와야 합니다. 이렇게 하려면 PgsSnapshotsClient_create() 메서드를 호출하고 Android 활동을 전달하면 됩니다.

참고: C++ SDK 함수는 콜백을 통해 결과를 비동기적으로 반환합니다.

// Assuming 'android_activity' is a jobject referencing your Android Activity
PgsSnapshotsClient* snapshots_client = PgsSnapshotsClient_create(android_activity);

// ... use the client ...

// When done, destroy the client to free resources
// PgsSnapshotsClient_destroy(snapshots_client);

저장된 게임 표시

게임에서 플레이어에게 진행 상황을 저장하거나 복원하는 옵션을 제공할 때마다 Snapshots API를 통합할 수 있습니다. 개발을 간소화하기 위해 스냅샷 API는 기본 저장된 게임 선택 사용자 인터페이스 (UI)를 제공합니다. 이 UI를 실행하려면 PgsSnapshotsClient_showSelectSnapshotUI를 호출합니다.

// Callback function to handle the result of showing the UI
void OnShowSavedGamesUI(PgsStatusCode status_code, void* user_data) {
  if (status_code == PGS_STATUS_SUCCESS) {
    // UI was shown successfully. The player can now interact with it.
    // The game doesn't receive direct data back from this callback about
    // which snapshot was selected. Your game should typically provide options
    // to load or open snapshots by name after the UI is dismissed.
  } else {
    // Handle error or failure to show UI
  }
}

// Function to show the default Saved Games UI
void ShowSavedGamesUI(PgsSnapshotsClient* client, jobject activity) {
  const char* title = "See My Saves";
  bool allow_add_button = true;
  bool allow_delete_button = true;
  int max_snapshots = 5;

  PgsSnapshotsClient_showSelectSnapshotUI(
      client,
      activity,
      title,
      allow_add_button,
      allow_delete_button,
      max_snapshots,
      OnShowSavedGamesUI,
      NULL // user_data
  );
}

// Example usage:
// ShowSavedGamesUI(snapshots_client, android_activity);

저장된 게임 작성

저장된 게임에 콘텐츠를 저장하려면 다음 단계를 따르세요.

  1. PgsSnapshotsClient_open()을 사용하여 스냅샷을 비동기식으로 엽니다. 새 저장 파일을 만들려면 create_if_not_found를 true로 지정합니다.
  2. 결과는 PgsSnapshotsClient_OpenCallback에 제공됩니다. 성공하고 충돌이 없으면 PgsSnapshot*이 표시됩니다.
  3. 바이트 배열 (uint8_t*)로 저장할 데이터를 준비합니다.
  4. 저장을 설명하는 PgsSnapshotMetadataChange* 객체를 만듭니다.
  5. PgsSnapshotsClient_commitAndClose를 호출하여 변경사항을 Google 서버에 전송합니다.

    // Callback for commitAndClose
    void OnSnapshotCommitted(PgsStatusCode status_code, PgsSnapshotMetadata* metadata, void* user_data) {
        if (status_code == PGS_STATUS_SUCCESS) {
        // Save successful
        if (metadata) {
        // Metadata for the committed snapshot
        PgsSnapshotMetadata_Release(metadata);
      }
    } else {
        // Handle error
      }
    }
    
    // Function to write data to a snapshot
    void WriteSnapshot(PgsSnapshotsClient* client, PgsSnapshot* snapshot,
                   const uint8_t* data, size_t data_size,
                   const char* description /*, Bitmap coverImage */) {
    
    PgsSnapshotMetadataChange* metadataChange = NULL; // Placeholder
    
      // Commit the operation
      PgsSnapshotsClient_commitAndClose(
          client,
          snapshot,
          metadataChange,
          data,
          data_size,
          OnSnapshotCommitted,
          NULL // user_data
      );
    
      // if (metadataChange) PgsSnapshotMetadataChange_Release(metadataChange);
    }
    
    // Callback for opening the snapshot before writing
    void OnSnapshotOpenForWrite(PgsStatusCode status_code,
                            PgsSnapshot* snapshot,
                            PgsSnapshotConflict* conflict,
                            void* user_data) {
      if (status_code == PGS_STATUS_SUCCESS) {
        if (snapshot) {
          // Successfully opened/created. Now write to it.
         const char* save_data_str = "MY_GAME_SAVE_DATA";
         const uint8_t* data = (const uint8_t*)save_data_str;
         size_t data_size = strlen(save_data_str);
    
          WriteSnapshot((PgsSnapshotsClient*)user_data, snapshot, data, data_size, "My Save Description");
          // PgsSnapshot_destroy(snapshot) is likely called after commitAndClose by the SDK
        } else if (conflict) {
          // Handle conflict before writing, or open with a policy that auto-resolves.
          PgsSnapshotConflict_destroy(conflict);
        }
      } else {
        // Handle error opening
      }
    }
    
    // Example: Open and write to a snapshot
    void OpenAndWriteExample(PgsSnapshotsClient* client, const char* snapshot_name) {
    PgsSnapshotsClient_open(
      client,
      snapshot_name,
      true, // create_if_not_found
      kPgsSnapshotConflictPolicyManual, // Or another policy
      OnSnapshotOpenForWrite,
      client // user_data
    );
    }

저장된 게임 로드

저장된 게임을 검색하려면 다음 단계를 따르세요.

  1. PgsSnapshotsClient_open()를 사용하여 이름으로 스냅샷을 비동기식으로 엽니다.
  2. PgsSnapshotsClient_OpenCallback에서 성공하면 데이터에 액세스합니다. API는 uint8_t* 데이터와 크기를 가져오는 방법을 제공하지만 PgsSnapshot 또는 연결된 PgsSnapshotContents에서 바이트를 읽는 방법은 이 문서에 자세히 설명되어 있지 않습니다.

    // Assuming functions exist to read data from PgsSnapshotContents
    // For example, PgsSnapshotContents* PgsSnapshot_getContents(PgsSnapshot* snapshot);
    // For example, bool PgsSnapshotContents_readFully(PgsSnapshotContents* contents, uint8_t** out_data, size_t* out_size);
    // For example, void PgsSnapshotContents_releaseData(uint8_t* data);
    
    void OnSnapshotOpenForRead(PgsStatusCode status_code,
                           PgsSnapshot* snapshot,
                           PgsSnapshotConflict* conflict,
                           void* user_data) {
        if (status_code == PGS_STATUS_SUCCESS) {
        if (snapshot) {
        // Successfully opened. Now read from it.
        // THE FOLLOWING IS HYPOTHETICAL based on common patterns:
        // PgsSnapshotContents* contents = PgsSnapshot_getContents(snapshot);
        // uint8_t* data = NULL;
        // size_t data_size = 0;
        // if (contents && PgsSnapshotContents_readFully(contents, &data, &data_size)) {
        //   // Successfully read data
        //   Log("Snapshot data loaded, size: %zu", data_size);
        //   ... process data ...
        //   PgsSnapshotContents_releaseData(data);
        // }
        // PgsSnapshotContents_destroy(contents); // If necessary
          PgsSnapshot_destroy(snapshot);
        } else if (conflict) {
          // Handle conflict
          Log("Snapshot open resulted in a conflict.");
          PgsSnapshotConflict_destroy(conflict);
        }
      } else {
        // Handle error opening
        Log("Error while opening Snapshot: %d", status_code);
      }
    }
    
    // Example: Load a specific saved game
    void LoadSnapshotByName(PgsSnapshotsClient* client, const char* snapshot_name) {
      int conflictResolutionPolicy = kPgsSnapshotConflictPolicyMostRecentlyModified;
    
      PgsSnapshotsClient_open(
          client,
          snapshot_name,
          false, // create_if_not_found
          conflictResolutionPolicy,
          OnSnapshotOpenForRead,
          NULL // user_data
      );
    }

저장된 게임 충돌 처리

PgsSnapshotsClient_open 콜백이 호출될 때 conflict 매개변수가 NULL이 아니면 충돌이 발생한 것이므로 PgsSnapshotsClient_resolveConflict를 사용하여 충돌을 해결합니다.

/// @brief Asynchronously resolves a snapshot conflict.
///
/// @param snapshots_client The client handle.
/// @param conflict_id The ID of the conflict to resolve.
/// @param snapshot_id The ID of the snapshot to use for resolution.
/// @param metadata_change The metadata changes to apply to the snapshot, or
/// NULL for no changes.
/// @param contents The contents to resolve the conflict with.
/// @param callback Function to be called with result of asynchronous
/// operation. See PgsSnapshotsClient_OpenCallback.
/// @param user_data Arbitrary data pointer to be passed back to callback.
void PgsSnapshotsClient_resolveConflict(
    PgsSnapshotsClient* snapshots_client,
    const char* conflict_id,
    const char* snapshot_id,
    PgsSnapshotMetadataChange* metadata_change,
    PgsSnapshotContents* contents,
    PgsSnapshotsClient_OpenCallback callback,
    void* user_data);