> ## Documentation Index
> Fetch the complete documentation index at: https://playwave.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# isPcCafeUser 디버그 스크립트

> PlayWaveServer.isPcCafeUser 의 반환값을 주기적으로 출력해 세션 상태와 PC방 판정을 확인합니다.

`PlayWaveServer.isPcCafeUser(player)` 의 반환값을 주기적으로 콘솔에 찍어서, 세션 상태와 PC방 판정이 제대로 들어오는지 확인하는 용도의 스크립트입니다.

## 설치

<Steps>
  <Step title="Roblox Studio에서 프로젝트 열기" />

  <Step title="ServerScriptService에 Script 새로 만들기">
    우클릭 → `Insert Object` → `Script`
  </Step>

  <Step title="이름을 PlayWaveDebug로 변경" />

  <Step title="아래 코드 붙여넣기">
    ```lua theme={null}
    -- PlayWaveDebug (Server Script, ServerScriptService)
    local Players = game:GetService("Players")
    local ServerScriptService = game:GetService("ServerScriptService")

    local PlayWaveSetup = ServerScriptService:WaitForChild("PlayWaveSetup")
    local PlayWaveServer = require(PlayWaveSetup:WaitForChild("PlayWaveServer"))

    while true do
        local players = Players:GetPlayers()
        if #players == 0 then
            print("[PlayWaveDebug] no players")
        else
            for _, player in ipairs(players) do
                print("[PlayWaveDebug] isPcCafeUser:", player.Name, "->", PlayWaveServer.isPcCafeUser(player))
            end
        end
        task.wait(3)
    end
    ```
  </Step>
</Steps>

## 코드 설명

### `game:GetService("...")`

Roblox 내장 서비스에 접근하는 표준 방법. `Players` 는 접속 중인 플레이어 관리, `ServerScriptService` 는 서버 스크립트가 담기는 컨테이너.

### `ServerScriptService:WaitForChild("PlayWaveSetup")`

`ServerScriptService` 의 자식 중 **이름이 `PlayWaveSetup` 인 인스턴스**를 찾아서 반환합니다. 만약 아직 없으면 **생길 때까지 기다림**.

왜 그냥 `ServerScriptService.PlayWaveSetup` 이 아니라 `WaitForChild` 를 쓰냐면:

* Roblox 에서 `ServerScriptService` 의 자식 스크립트들은 **병렬로 실행 시작**되고 로드 순서가 보장되지 않음
* 이 디버그 스크립트가 `PlayWaveSetup` 보다 먼저 실행되면 `PlayWaveSetup` 인스턴스가 아직 트리에 **안 보일 수 있음**
* `.` 직접 접근 → 이 시점에 없으면 즉시 에러
* `:WaitForChild()` → 존재할 때까지 yield (쓰레드 대기)

**"트리 계층을 타고 내려가는 안전한 접근자"** 라고 생각하면 됩니다.

### `require(ModuleScript)`

Roblox 의 모듈 로드 함수. 대상이 `ModuleScript` 인스턴스여야 하고:

1. 처음 호출될 때 → 그 스크립트를 한 번 실행하고, 거기서 `return` 한 값을 저장
2. 두 번째부터 → 다시 실행 안 하고 **저장된 같은 값**을 반환 (캐시)

```lua theme={null}
local A = require(PlayWaveServer)  -- 첫 호출: 모듈 실행
local B = require(PlayWaveServer)  -- 캐시된 같은 테이블 반환
-- A 와 B 는 완전히 같은 테이블. A.foo = 1 하면 B.foo 도 1
```

이 덕분에 **여러 스크립트가 같은 모듈을 require 해도 상태가 공유됩니다.** PlayWaveSetup 에서 `init()` 으로 세팅한 `activeSessions` 를 이 디버그 스크립트가 그대로 읽을 수 있는 이유.

### `PlayWaveSetup:WaitForChild("PlayWaveServer")`

`PlayWaveSetup` Script 아래에 자식으로 들어있는 **`PlayWaveServer` ModuleScript** 를 기다려서 가져옴. 실제 트리 구조:

```
ServerScriptService/
  PlayWaveSetup          (Script)        ← 여기서 require 함
    ApiKey               (StringValue)
    ApiUrl               (StringValue)
    PlayWaveServer       (ModuleScript)  ← require 대상
```

### `while true do ... task.wait(3) end`

무한 루프. `task.wait(3)` 로 3초마다 양보하면서 반복. `task.wait` 없이 `while true` 만 쓰면 **서버 스케줄러를 블로킹**해서 다른 스크립트·이벤트가 다 멈춥니다.

### `Players:GetPlayers()`

현재 접속 중인 플레이어 목록 (Player 인스턴스 배열) 반환. `#players` 는 배열 길이.

## 실행

Studio 에서 **Play** 로 게임을 시작하면 **Output** 창에 3초마다 로그가 찍힙니다.

## 기대 출력

### 서버만 시작 (플레이어 없음)

```
[PlayWaveDebug] no players
[PlayWaveDebug] no players
...
```

### 플레이어 입장 직후 (OTT verify 전)

```
[PlayWaveDebug] isPcCafeUser: Player1 -> false
```

입장 \~ OTT API 응답까지 약간의 지연이 있어서 초기엔 `false` 가 나올 수 있습니다.

### OTT verify 완료 후 (일반 유저)

```
[PlayWaveDebug] isPcCafeUser: Player1 -> false
```

일반 유저는 계속 `false`.

### OTT verify 완료 후 (PC방 유저)

```
[PlayWaveDebug] isPcCafeUser: Player1 -> true
```

PC방 유저는 `true` 로 바뀌고 이후 유지됨. `[PlayWave] PC cafe detected` 로그도 함께 찍힘.

### 텔레포트로 넘어온 서브플레이스

```
[PlayWaveDebug] isPcCafeUser: Player1 -> true
```

이전 서버의 세션 상태가 `TeleportData` 로 전달되어 즉시 반영됨.

## 문제 해결

<AccordionGroup>
  <Accordion title="attempt to call a nil value" icon="circle-exclamation">
    `PlayWaveServer.isPcCafeUser` 가 모듈에 없다는 뜻. **SDK 가 옛날 버전**입니다.

    해결:

    1. 최신 `PlayWavePlugin.plugin` 파일을 플러그인 폴더에 덮어쓰기
       * macOS: `~/Documents/Roblox/Plugins/`
       * Windows: `%LOCALAPPDATA%/Roblox/Plugins/`
    2. Studio 재시작
    3. 툴바의 **PlayWave Setup** → **Install SDK** 다시 실행

    <Warning>
      재설치 시 `PlayWaveSetup` 스크립트의 편집 내용이 초기화되므로, `onPcCafe` 콜백 등을 수정한 게 있으면 백업 필수.
    </Warning>
  </Accordion>

  <Accordion title="Infinite yield possible on WaitForChild('PlayWaveSetup')" icon="hourglass">
    `WaitForChild` 가 5초 이상 기다려도 대상을 못 찾았다는 경고. **SDK 가 설치되지 않은 상태**입니다. 툴바에서 **Install SDK** 실행.
  </Accordion>

  <Accordion title="계속 false 만 나옴 (일반 유저로 테스트 중)" icon="circle-check">
    정상 동작. PC방 판정은 PlayWave 런처를 통해 PC방 환경에서 입장했을 때만 `true`.
  </Accordion>

  <Accordion title="[PlayWave] No OTT found, skipping verify 경고" icon="circle-info">
    플레이어가 PlayWave 런처를 거치지 않고 일반 경로로 입장한 경우. 이 유저는 세션 자체가 만들어지지 않으므로 항상 `false` 반환. 정상.
  </Accordion>
</AccordionGroup>

## 주의사항

<Warning>
  **디버그 전용**입니다. 3초마다 출력이 쌓여서 프로덕션 환경에서는 로그가 지저분해짐 → 테스트 끝나면 Script 를 Disable 하거나 삭제하세요.
</Warning>

* 스크립트 상단의 `task.wait(3)` 값을 바꾸면 주기 조절 가능.

## 관련 API

* `PlayWaveServer.isPcCafeUser(player)` — boolean 반환. 세션 없으면 `false`.
* `PlayWaveServer.init({ onPcCafe = function(player) ... end })` — PC방 유저 입장 순간 1회 호출되는 콜백. "입장 시 보상 지급" 용도라면 이쪽을 우선 사용.
