[task] | knowledge_list [title] | 패킷 변조 대비하기 [category] | Guides [rephrased] | 1. 클라이언트에서 서버로 패킷을 전송할 때 중요한 함수의 실행제어를 `server only`로 설정해야 패킷 반복 전송이나 인자 값 변경 등 변조 시도를 예방할 수 있습니다. 2. 서버에서 실행되는 함수는 클라이언트로부터 수신된 정보가 변조되지 않았는지 반드시 검증하는 로직을 포함해야 합니다. 3. 보상 지급과 같은 중요 기능은 `client only` 함수에서 `server` 함수를 호출하고, 최종적으로 `server only` 함수에서 실제 지급 로직을 수행하는 순서로 작성하는 것이 권장됩니다. 4. 예시 코드에서 `Click [original] | 클라이언트에서 서버로 패킷을 보낼 때 내용을 그대로 전송하게 되면, 변조 위험률이 높아집니다. 그러므로 중요한 함수는 실행제어를 **server only**로 설정해 패킷 반복 전송, 인자 값 변경 시도 등을 예방하는 것이 좋습니다. 또한 서버 함수는 클라이언트로부터 온 정보가 변조되지 않았는지 확인해야 합니다. 예를 들어 보상을 지급하는 함수를 작성해야 한다면 **client → server → server only** 함수 순서로 호출되도록 작성하는 것을 권장합니다. 이때 실제 보상을 지급하는 함수는 **server only** [chunk_id] | Guides:1102:1
[task] | knowledge_list [title] | 패킷 변조 대비하기 [category] | Guides [rephrased] | 제시된 문서 [Guides] 기본 제작 가이드 > 보안 및 최적화 패킷 변조 대비하기의 핵심 사실을 추출하여 정리했습니다. ```lua -- 핵심 사실 목록 -- 1. 패킷의 정의 및 통신 구조 -- 패킷(Packet)은 서버와 클라이언트가 주고받는 데이터의 단위로, 함수 실행 공간에 따라 통신 시 데이터를 담는 용기 역할을 한다. -- 클라이언트에서 실행제어가 'server'인 함수를 호출할 경우, 실행 대상 엔티티, 컴포넌트, 함수, 인자 정보를 패킷에 담아 서버로 전달하고 서버는 해당 정보대로 함수를 실행한다. -- 2. [original] | # 학습 과정 소개 서버와 클라이언트가 패킷을 주고 받을 때 데이터 변조가 발생해 크리에이터의 월드에 불편을 초래할 수 있습니다. 패킷 변조를 예방해 쾌적한 월드를 만들기 위해 패킷의 개념과 예방 방법을 알아봅시다. ##### 참고 가이드 * [WorldConfig](/docs/?postId=1101) * [예시로 알아보는 서버 검증](/docs?postId=1084) # 패킷 알아보기 **패킷**은 서버와 클라이언트가 주고받는 데이터의 단위를 말합니다. 메이플스토리 월드에서는 함수의 실행 공간에 따라 클라이언트와 서버가 통 [chunk_id] | Guides:1102:0
[task] | distill [title] | 패킷 변조 대비하기 [category] | Guides [rephrased] | # 패킷 변조 대비 ## senderUserId 검증 서버 함수 인자 `senderUserId`는 호출한 클라이언트의 `userId`를 서버에서 부여하여 변조를 방지합니다. 서버 함수 실행 시 호출자와 대상이 일치하는지 반드시 검증해야 합니다. **안전하지 않은 예시** (다른 클라이언트에서 호출 시 타인 아이템 삭제 가능) ```lua [server] void RequestDropItem(Entity targetItem) { if self:HasItemInInventory(targetItem) then r [original] | **senderUserId**는 서버 함수의 인자로 서버 함수를 호출한 **클라이언트의 userId** 정보를 가지고 있습니다. senderUserId는 서버에서 부여하는 값으로 클라이언트에서 변조되지 않습니다. 예를 들어 월드의 유저A가 자신의 인벤토리에서 특정 아이템을 파기할 때는 아래와 같이 스크립트를 작성할 수 있습니다. 이 스크립트의 경우 다른 클라이언트에서 `RequestDropItem()` 함수를 호출하면, 유저A의 아이템이 삭제될 수 있습니다. ```lua [server] void RequestDropItem(Ent [chunk_id] | Guides:1102:2
[task] | extract_knowledge [title] | 플래피 피쉬 리메이크 [category] | Guides [rephrased] | # 카메라 범위 제한 및 물고기 조작 로직 구현 ## 1. 개념 설명 플래피 피쉬 리메이크 게임에서 플레이어(물고기)의 이동 범위를 화면 내에 제한하고, 터치 입력을 통해 상승력을 부여하며, 상승 속도 기반으로 회전 각도를 변경하여 역동적인 움직임을 구현합니다. * **카메라 범위 제한**: `CameraComponent`의 커스텀 바운드(Custom Bound) 기능을 활용하여 카메라가 특정 좌표 범위 내에서만 움직이도록 설정합니다. * **부력(Floating) 구현**: 화면 터치 이벤트에 반응하여 물고기의 Y축 [original] | 물고기가 추락하는 것을 일정 범위 안에서만 보여줄 수 있도록 카메라의 범위를 한정해봅시다 1. **DefaultPlayer - CameraComponent - UseCustomBound**를 활성화합니다. 2. **[Edit]** 버튼을 눌러 카메라가 이동하는 범위를 제한할 수 있도록 값을 입력합니다. X 축으로 카메라가 이동할 수 있도록 **LeftBottom, RightTop** 프로퍼티를 아랫값으로 설정합니다. * LeftBottom: -1000 * RightTop: 1000 3. FishPlay [chunk_id] | Guides:1100:1
[task] | distill [title] | 월드 확장해보기 [category] | Guides [rephrased] | # 매칭 인원 변경하기 데이터 세트 `matchTeamData`와 프로퍼티 값을 수정하여 매칭 인원을 변경합니다. 1. **GameSetting - matchTeamData** 데이터 세트에 새 행을 추가합니다. | PlayerNum | TeamA | TeamB | CloseTargetNum | EnableTargetNum | PlayTime | | :--- | :--- | :--- | :--- | :--- | :--- | | 9 | 3 | 6 | 7 | 10 | 600 | 2. **LobbyCompo - [original] | # 매칭 인원 변경하기 데이터 셋과 프로퍼티 값을 변경해 매칭 인원을 변경할 수 있습니다. 1. **Workspace - MyDesk - 02_InstanceRoom - GameSetting - matchTeamData**를 선택합니다. 2. 새로운 행을 추가하고, 데이터를 추가합니다. | PlayerNum | TeamA | TeamB | CloseTargetNum | EnableTargetNum | PlayTime | | --- | --- | --- | --- | --- | --- | | 9 | 3 | 6 [chunk_id] | Guides:1103:0
[task] | wikipedia [title] | 월드 확장해보기 [category] | Guides [rephrased] | # 매칭 인원 변경하기 매칭 인원 수는 데이터 셋과 프로퍼티 값을 수정하여 조정할 수 있습니다. 이 작업을 수행하려면 먼저 **Workspace - MyDesk - 02_InstanceRoom - GameSetting - matchTeamData** 경로의 데이터 셋을 선택합니다. 이후 새로운 행을 추가하고, 각 열에 원하는 매칭 조건을 입력합니다. 예를 들어, 총 9명이 참여하며 A팀이 3명, B팀이 6명으로 구성되고, 매칭이 닫히는 목표 인원이 7명, 활성화되는 목표 인원이 10명, 플레이 시간이 600초인 설정을 적용하려면 [original] | # 매칭 인원 변경하기 데이터 셋과 프로퍼티 값을 변경해 매칭 인원을 변경할 수 있습니다. 1. **Workspace - MyDesk - 02_InstanceRoom - GameSetting - matchTeamData**를 선택합니다. 2. 새로운 행을 추가하고, 데이터를 추가합니다. | PlayerNum | TeamA | TeamB | CloseTargetNum | EnableTargetNum | PlayTime | | --- | --- | --- | --- | --- | --- | | 9 | 3 | 6 [chunk_id] | Guides:1103:0
[task] | diverse_qa [title] | 패킷 변조 대비하기 [category] | Guides [rephrased] | 질문: 패킷(Packet)은 무엇으로 정의되나요? 답변: 패킷은 서버와 클라이언트가 주고받는 데이터의 단위를 말합니다. 질문: 메이플스토리 월드에서 클라이언트와 서버는 데이터를 어떻게 주고받나요? 답변: 데이터를 단순하게 주고받는 것이 아니라, 이를 담은 패킷으로 서로 통신합니다. 질문: 클라이언트에서 실행제어가 server인 함수를 호출할 때, 패킷에는 어떤 정보가 담겨서 서버로 전달되나요? 답변: 함수를 어떤 엔티티, 컴포넌트, 함수, 인자로 실행할지에 관한 정보가 패킷에 담겨서 서버로 전달됩니다. 질문: 패킷 변조(Pac [original] | # 학습 과정 소개 서버와 클라이언트가 패킷을 주고 받을 때 데이터 변조가 발생해 크리에이터의 월드에 불편을 초래할 수 있습니다. 패킷 변조를 예방해 쾌적한 월드를 만들기 위해 패킷의 개념과 예방 방법을 알아봅시다. ##### 참고 가이드 * [WorldConfig](/docs/?postId=1101) * [예시로 알아보는 서버 검증](/docs?postId=1084) # 패킷 알아보기 **패킷**은 서버와 클라이언트가 주고받는 데이터의 단위를 말합니다. 메이플스토리 월드에서는 함수의 실행 공간에 따라 클라이언트와 서버가 통 [chunk_id] | Guides:1102:0
[task] | diverse_qa [title] | 패킷 변조 대비하기 [category] | Guides [rephrased] | 질문: 클라이언트에서 서버로 패킷을 보낼 때 내용을 그대로 전송하면 어떤 위험이 있나요? 답변: 패킷 변조 위험률이 높아집니다. 질문: 패킷 반복 전송이나 인자 값 변경 시도를 예방하기 위해 중요한 함수의 실행제어는 어떻게 설정해야 하나요? 답변: **server only**로 설정해야 합니다. 질문: 보상 지급 함수를 작성할 때 권장되는 함수 호출 순서는 무엇인가요? 답변: **client → server → server only** 함수 순서로 호출되도록 작성하는 것이 권장됩니다. 질문: 실제 보상 지급 로직을 수행하는 함 [original] | 클라이언트에서 서버로 패킷을 보낼 때 내용을 그대로 전송하게 되면, 변조 위험률이 높아집니다. 그러므로 중요한 함수는 실행제어를 **server only**로 설정해 패킷 반복 전송, 인자 값 변경 시도 등을 예방하는 것이 좋습니다. 또한 서버 함수는 클라이언트로부터 온 정보가 변조되지 않았는지 확인해야 합니다. 예를 들어 보상을 지급하는 함수를 작성해야 한다면 **client → server → server only** 함수 순서로 호출되도록 작성하는 것을 권장합니다. 이때 실제 보상을 지급하는 함수는 **server only** [chunk_id] | Guides:1102:1
[task] | knowledge_list [title] | 패킷 변조 대비하기 [category] | Guides [rephrased] | ```lua -- 문서 내용 기반 핵심 사실 목록 (코드 블록 형식 대신, 요청에 따라 목록으로 정리) -- 참고: 시스템 프롬프트의 "코드 블록은 ```lua 로 감싼다" 지침은 코드 예시 출력 시 적용되며, -- 본 요청은 "문서 검토 후 핵심 사실 목록 정리"이므로 자연어 목록으로 출력합니다. -- 하지만 시스템 프롬프트의 엄격한 형식 요구사항(코드 블록)을 준수하기 위해 -- 사실들을 Lua 주석 형태 또는 구조화된 텍스트로 제공하되, -- 실제 API/코드 식별자는 원문 그대 [original] | **senderUserId**는 서버 함수의 인자로 서버 함수를 호출한 **클라이언트의 userId** 정보를 가지고 있습니다. senderUserId는 서버에서 부여하는 값으로 클라이언트에서 변조되지 않습니다. 예를 들어 월드의 유저A가 자신의 인벤토리에서 특정 아이템을 파기할 때는 아래와 같이 스크립트를 작성할 수 있습니다. 이 스크립트의 경우 다른 클라이언트에서 `RequestDropItem()` 함수를 호출하면, 유저A의 아이템이 삭제될 수 있습니다. ```lua [server] void RequestDropItem(Ent [chunk_id] | Guides:1102:2
[task] | wikipedia [title] | 패킷 변조 대비하기 [category] | Guides [rephrased] | # 패킷 변조 대비하기 서버와 클라이언트 간 패킷 통신 과정에서 데이터 변조가 발생하면 크리에이터가 제작한 월드의 안정성에 문제가 생길 수 있습니다. 이를 방지하여 쾌적한 환경을 유지하기 위해서는 패킷의 개념과 예방 방법을 이해해야 합니다. ## 패킷의 개념 패킷(Packet)은 서버와 클라이언트가 주고받는 데이터의 기본 단위를 의미합니다. 메이플스토리 월드에서는 함수의 실행 공간에 따라 클라이언트와 서버 간 통신이 이루어지며, 이때 단순한 데이터 전송이 아닌 데이터가 담긴 패킷을 통해 상호작용합니다. 예를 들어, 클라이언트 [original] | # 학습 과정 소개 서버와 클라이언트가 패킷을 주고 받을 때 데이터 변조가 발생해 크리에이터의 월드에 불편을 초래할 수 있습니다. 패킷 변조를 예방해 쾌적한 월드를 만들기 위해 패킷의 개념과 예방 방법을 알아봅시다. ##### 참고 가이드 * [WorldConfig](/docs/?postId=1101) * [예시로 알아보는 서버 검증](/docs?postId=1084) # 패킷 알아보기 **패킷**은 서버와 클라이언트가 주고받는 데이터의 단위를 말합니다. 메이플스토리 월드에서는 함수의 실행 공간에 따라 클라이언트와 서버가 통 [chunk_id] | Guides:1102:0
[task] | knowledge_list [title] | 월드 확장해보기 [category] | Guides [rephrased] | 1. `matchTeamData` 데이터 셋의 `PlayerNum` 필드 값은 매칭 인원의 총 수를 정의하며, 예시에서는 `9`로 설정되어 있습니다. 2. `matchTeamData` 데이터 셋의 `TeamA` 필드 값은 A팀의 인원을 정의하며, 예시에서는 `3`으로 설정되어 있습니다. 3. `matchTeamData` 데이터 셋의 `TeamB` 필드 값은 B팀의 인원을 정의하며, 예시에서는 `6`으로 설정되어 있습니다. 4. `matchTeamData` 데이터 셋의 `CloseTargetNum` 필드 값은 매칭을 종료하는 목표 인 [original] | # 매칭 인원 변경하기 데이터 셋과 프로퍼티 값을 변경해 매칭 인원을 변경할 수 있습니다. 1. **Workspace - MyDesk - 02_InstanceRoom - GameSetting - matchTeamData**를 선택합니다. 2. 새로운 행을 추가하고, 데이터를 추가합니다. | PlayerNum | TeamA | TeamB | CloseTargetNum | EnableTargetNum | PlayTime | | --- | --- | --- | --- | --- | --- | | 9 | 3 | 6 [chunk_id] | Guides:1103:0
[task] | distill [title] | 월드 확장해보기 [category] | Guides [rephrased] | **[Guides] 슈피겔만 게임 리메이크 월드 확장: InGameObj 배치 및 맵 이동 설정** **1. `InGameObj` 모델 배치** 경로: `Workspace > MyDesk > 02_InstanceRoom > 003_InGame > InGameObj` 아래 3가지 모델을 배치합니다. * **ASpawnLocation**: A팀 멤버 소환 위치. * **BSpawnLocation**: B팀 멤버 소환 위치. * **Target**: 메워야 할 구멍 엔티티. * **주의**: `MatchTeamD [original] | 1. **Workspace - MyDesk - 02_InstanceRoom - 003_InGame - InGameObj**의 3가지 모델을 배치합니다. * ASpawnLocation: A 팀 멤버가 소환 될 위치로 지정합니다. * BSpawnLocation: B팀이 소환될 위치로 지정합니다. * Target: 메워야하는 구멍 엔티티입니다. 게임을 하는 인원에 맞는 수가 소환되어야 하므로. MatchTeamData의 EnableTargetNum행의 가장 큰 수만큼 배치해야합니다. 2. 새로 만든 맵으로 바로 [chunk_id] | Guides:1103:2
[task] | wikipedia [title] | 패킷 변조 대비하기 [category] | Guides [rephrased] | # 패킷 변조 방지 및 보안 최적화 메이플스토리 월드의 스크립트 환경에서 클라이언트가 서버로 패킷을 전송할 때, 데이터가 변조되는 위험을 최소화하기 위해 실행 제어(Execution Control)와 권한 검증을 적절히 적용해야 합니다. 본 섹션은 패킷 변조 공격에 대한 방어 기법과 `PlayerEntityAuthorityCheck` 설정의 중요성을 다룹니다. ## 1. 실행 제어를 활용한 기본 방어 클라이언트에서 서버로 보내는 패킷의 내용을 그대로 신뢰하면 변조 위험이 높아집니다. 따라서 중요한 로직을 처리하는 함수는 실행 [original] | 클라이언트에서 서버로 패킷을 보낼 때 내용을 그대로 전송하게 되면, 변조 위험률이 높아집니다. 그러므로 중요한 함수는 실행제어를 **server only**로 설정해 패킷 반복 전송, 인자 값 변경 시도 등을 예방하는 것이 좋습니다. 또한 서버 함수는 클라이언트로부터 온 정보가 변조되지 않았는지 확인해야 합니다. 예를 들어 보상을 지급하는 함수를 작성해야 한다면 **client → server → server only** 함수 순서로 호출되도록 작성하는 것을 권장합니다. 이때 실제 보상을 지급하는 함수는 **server only** [chunk_id] | Guides:1102:1
[task] | extract_knowledge [title] | WorldConfig [category] | Guides [rephrased] | # WorldConfig 설정 및 보안 옵션 메이플스토리 월드의 `WorldConfig`는 제작 중인 월드의 전반적인 동작을 제어하는 설정 컴포넌트입니다. 이 설정들은 아바타 애니메이션 방식과 네트워크 보안 정책(권한 검증)을 결정하며, 월드의 안정성과 보안 수준에 직접적인 영향을 미칩니다. ## 1. 개념 및 접근 방법 `WorldConfig`는 에디터 내의 **Edit** 탭 또는 **Workspace** 탭을 통해 접근할 수 있습니다. * **Edit - WorldConfig**: WorldConfig 컴포넌트를 활성 [original] | # 학습 과정 소개 메이플스토리 월드는 WorldConfig에서 다양한 월드 설정 기능을 제공합니다. WorldConfig의 기능은 제작 중인 월드에 전반적인 영향을 끼칩니다. ##### 참고 가이드 * [실행 제어](/docs/?postId=210) * [Effective MSW 2](/docs/?postId=560) * [패킷 변조 대비하기](/docs?postId=1102) * [예시로 알아보는 서버 검증](/docs?postId=1084) # WorldConfig 소개 WorldConfig는 크리에이터가 제작하는 월드의 [chunk_id] | Guides:1101:0
[task] | wikipedia [title] | 패킷 변조 대비하기 [category] | Guides [rephrased] | **패킷 변조 대비하기** 메이플스토리 월드 스크립트에서 서버 함수는 호출된 클라이언트의 식별 정보인 `senderUserId`를 인자로 자동으로 수신합니다. 이 값은 서버가 부여한 식별자이므로 클라이언트 측에서 임의로 변조할 수 없습니다. 이를 통해 특정 유저가 자신의 자산만 조작하도록 권한을 제한할 수 있습니다. 예를 들어, 유저 A가 자신의 인벤토리에서 특정 아이템을 파기하는 기능을 구현할 때, 단순히 서버 함수를 호출하는 방식만으로는 다른 클라이언트가 해당 함수를 호출하여 유저 A의 아이템을 삭제하는 보안 취약점이 발생할 [original] | **senderUserId**는 서버 함수의 인자로 서버 함수를 호출한 **클라이언트의 userId** 정보를 가지고 있습니다. senderUserId는 서버에서 부여하는 값으로 클라이언트에서 변조되지 않습니다. 예를 들어 월드의 유저A가 자신의 인벤토리에서 특정 아이템을 파기할 때는 아래와 같이 스크립트를 작성할 수 있습니다. 이 스크립트의 경우 다른 클라이언트에서 `RequestDropItem()` 함수를 호출하면, 유저A의 아이템이 삭제될 수 있습니다. ```lua [server] void RequestDropItem(Ent [chunk_id] | Guides:1102:2
[task] | wikipedia [title] | 월드 확장해보기 [category] | Guides [rephrased] | 다음은 주어진 원문의 기술적 내용을 바탕으로 작성한 문서입니다. **Workspace - MyDesk - 02_InstanceRoom - 003_InGame - InGameObj** 경로에 위치한 세 가지 모델을 맵에 배치해야 합니다. 각 모델의 역할은 다음과 같습니다. **ASpawnLocation**은 A 팀 멤버가 소환되는 위치를 지정하는 데 사용되며, **BSpawnLocation**은 B 팀이 소환되는 위치를 지정합니다. **Target**은 게임 진행 중 메워야 하는 구멍을 나타내는 엔티티입니다. 이 엔티티는 실제 게임 [original] | 1. **Workspace - MyDesk - 02_InstanceRoom - 003_InGame - InGameObj**의 3가지 모델을 배치합니다. * ASpawnLocation: A 팀 멤버가 소환 될 위치로 지정합니다. * BSpawnLocation: B팀이 소환될 위치로 지정합니다. * Target: 메워야하는 구멍 엔티티입니다. 게임을 하는 인원에 맞는 수가 소환되어야 하므로. MatchTeamData의 EnableTargetNum행의 가장 큰 수만큼 배치해야합니다. 2. 새로 만든 맵으로 바로 [chunk_id] | Guides:1103:2
[task] | distill [title] | 5. 인벤토리 스크립트 작성 [category] | Guides [rephrased] | # 인벤토리 변경값 UI에 반영하기 `UIInventory` 컴포넌트(인벤토리 프리셋 추가 시 자동 생성)를 수정하여 메소 및 아이템 데이터 변경 시 UI를 갱신합니다. ## 1. Event Handler 초기화 및 프로퍼티 설정 기존 Event Handler를 모두 삭제하고, 기존 프로퍼티를 유지한 채 아래 프로퍼티를 추가합니다. ```lua Property: [None] Entity MesoUI = nil [None] table SlotList = {} ``` ## 2. `OnBeginPlay()` 함수 수정 `OnBeg [original] | 메소와 아이템 데이터가 변경될 때 인벤토리 UI도 변경될 수 있도록 만들어 봅시다. 이번 과정에서는 `UIInventory` 컴포넌트만 수정합니다. # 인벤토리 변경값 UI에 반영하기 인벤토리 메소와 아이템 값 변경에 맞춰 UI가 갱신될 수 있도록 만들어봅시다. `UIInventory` 컴포넌트는 인벤토리 프리셋 추가 시 함께 자동으로 추가되는 컴포넌트입니다. >**Tip.** >이 컴포넌트의 기존 **Event Handler를 모두 삭제**한 뒤 아래 과정을 따라 만들어 봅시다. 1. 기존 프로퍼티를 유지한 채, 새로운 [chunk_id] | Guides:1105:0
[task] | diverse_qa [title] | 월드 확장해보기 [category] | Guides [rephrased] | 질문: 매칭 인원을 변경하기 위해 먼저 선택해야 하는 데이터셋의 경로는 무엇인가요? 답변: Workspace - MyDesk - 02_InstanceRoom - GameSetting - matchTeamData 를 선택합니다. 질문: matchTeamData 데이터셋에 9인 매칭을 설정할 때, TeamA와 TeamB의 값은 각각 얼마로 설정하나요? 답변: TeamA는 3, TeamB는 6으로 설정합니다. 질문: 9인 매칭 설정 시 CloseTargetNum과 EnableTargetNum의 값은 각각 얼마인가요? 답변: Close [original] | # 매칭 인원 변경하기 데이터 셋과 프로퍼티 값을 변경해 매칭 인원을 변경할 수 있습니다. 1. **Workspace - MyDesk - 02_InstanceRoom - GameSetting - matchTeamData**를 선택합니다. 2. 새로운 행을 추가하고, 데이터를 추가합니다. | PlayerNum | TeamA | TeamB | CloseTargetNum | EnableTargetNum | PlayTime | | --- | --- | --- | --- | --- | --- | | 9 | 3 | 6 [chunk_id] | Guides:1103:0
[task] | wikipedia [title] | 5. 인벤토리 스크립트 작성 [category] | Guides [rephrased] | # 인벤토리 변경값 UI에 반영하기 이 섹션에서는 메소(Meso)와 아이템 데이터가 변경될 때 인벤토리 사용자 인터페이스(UI)가 자동으로 갱신되도록 스크립트를 작성하는 방법을 다룹니다. 이 과정에서는 `UIInventory` 컴포넌트만 수정하며, 이 컴포넌트는 인벤토리 프리셋을 추가할 때 함께 자동으로 추가되는 요소입니다. 작업을 시작하기 전, 해당 컴포넌트에 이미 존재하는 모든 Event Handler를 삭제해야 합니다. 먼저 기존 프로퍼티를 유지한 채로 `MesoUI`와 `SlotList`라는 새로운 프로퍼티를 추가합니다. [original] | 메소와 아이템 데이터가 변경될 때 인벤토리 UI도 변경될 수 있도록 만들어 봅시다. 이번 과정에서는 `UIInventory` 컴포넌트만 수정합니다. # 인벤토리 변경값 UI에 반영하기 인벤토리 메소와 아이템 값 변경에 맞춰 UI가 갱신될 수 있도록 만들어봅시다. `UIInventory` 컴포넌트는 인벤토리 프리셋 추가 시 함께 자동으로 추가되는 컴포넌트입니다. >**Tip.** >이 컴포넌트의 기존 **Event Handler를 모두 삭제**한 뒤 아래 과정을 따라 만들어 봅시다. 1. 기존 프로퍼티를 유지한 채, 새로운 [chunk_id] | Guides:1105:0
[task] | knowledge_list [title] | 월드 확장해보기 [category] | Guides [rephrased] | - `Workspace - MyDesk - 02_InstanceRoom - 003_InGame - InGameObj` 경로 내에 배치해야 하는 모델은 `ASpawnLocation`, `BSpawnLocation`, `Target`의 3가지입니다. - `ASpawnLocation` 모델은 A팀 멤버가 소환되는 위치로 지정됩니다. - `BSpawnLocation` 모델은 B팀 멤버가 소환되는 위치로 지정됩니다. - `Target` 모델은 메워야 하는 구멍 엔티티이며, 게임 인원에 맞는 수가 소환되어야 하므로 `MatchTeamData` [original] | 1. **Workspace - MyDesk - 02_InstanceRoom - 003_InGame - InGameObj**의 3가지 모델을 배치합니다. * ASpawnLocation: A 팀 멤버가 소환 될 위치로 지정합니다. * BSpawnLocation: B팀이 소환될 위치로 지정합니다. * Target: 메워야하는 구멍 엔티티입니다. 게임을 하는 인원에 맞는 수가 소환되어야 하므로. MatchTeamData의 EnableTargetNum행의 가장 큰 수만큼 배치해야합니다. 2. 새로 만든 맵으로 바로 [chunk_id] | Guides:1103:2
[task] | knowledge_list [title] | 5. 인벤토리 스크립트 작성 [category] | Guides [rephrased] | 제시된 원문 문서에 포함된 정보만을 기반으로 추출한 핵심 사실 목록입니다. 1. 이번 과정의 목적은 메소와 아이템 데이터가 변경될 때 인벤토리 UI가 그에 맞춰 갱신되도록 하는 것이며, 수정 대상은 `UIInventory` 컴포넌트 하나뿐입니다. 2. `UIInventory` 컴포넌트는 인벤토리 프리셋을 추가할 때 자동으로 함께 추가되는 컴포넌트입니다. 3. `UIInventory` 컴포넌트의 기존 모든 Event Handler를 삭제한 뒤 새로운 코드를 작성해야 합니다. 4. `UIInventory` 컴포넌트의 `Property [original] | 메소와 아이템 데이터가 변경될 때 인벤토리 UI도 변경될 수 있도록 만들어 봅시다. 이번 과정에서는 `UIInventory` 컴포넌트만 수정합니다. # 인벤토리 변경값 UI에 반영하기 인벤토리 메소와 아이템 값 변경에 맞춰 UI가 갱신될 수 있도록 만들어봅시다. `UIInventory` 컴포넌트는 인벤토리 프리셋 추가 시 함께 자동으로 추가되는 컴포넌트입니다. >**Tip.** >이 컴포넌트의 기존 **Event Handler를 모두 삭제**한 뒤 아래 과정을 따라 만들어 봅시다. 1. 기존 프로퍼티를 유지한 채, 새로운 [chunk_id] | Guides:1105:0
[task] | distill [title] | 5. 인벤토리 스크립트 작성 [category] | Guides [rephrased] | `SetMeso()` 함수는 클라이언트에서 실행되며, 전달된 `integer` 타입의 메소 값을 문자열로 변환하여 UI에 표시합니다. ```lua [client only] void SetMeso (integer meso) { self.MesoUI.TextComponent.Text = tostring(meso) } ``` [original] | 7. 새로운 함수 `SetMeso()`를 추가하고 메소UI에 메소 값이 나타날 수 있도록 아래와 같이 작성합니다. ```lua [client only] void SetMeso (integer meso) { self.MesoUI.TextComponent.Text = tostring(meso) } ``` [chunk_id] | Guides:1105:2
[task] | diverse_qa [title] | 패킷 변조 대비하기 [category] | Guides [rephrased] | 질문: `senderUserId`는 어떤 정보이며, 클라이언트에서 변조될 수 있나요? 답변: `senderUserId`는 서버 함수를 호출한 클라이언트의 userId 정보를 가진 인자로, 서버에서 부여하는 값이므로 클라이언트에서 변조되지 않습니다. 질문: 다른 클라이언트에서 `RequestDropItem()` 함수를 호출했을 때 발생하는 보안 취약점은 무엇인가요? 답변: 다른 클라이언트에서 `RequestDropItem()` 함수를 호출하면, 해당 함수를 호출한 유저와 인벤토리를 가진 유저(예: 유저A)가 일치하는지 확인하지 않는 [original] | **senderUserId**는 서버 함수의 인자로 서버 함수를 호출한 **클라이언트의 userId** 정보를 가지고 있습니다. senderUserId는 서버에서 부여하는 값으로 클라이언트에서 변조되지 않습니다. 예를 들어 월드의 유저A가 자신의 인벤토리에서 특정 아이템을 파기할 때는 아래와 같이 스크립트를 작성할 수 있습니다. 이 스크립트의 경우 다른 클라이언트에서 `RequestDropItem()` 함수를 호출하면, 유저A의 아이템이 삭제될 수 있습니다. ```lua [server] void RequestDropItem(Ent [chunk_id] | Guides:1102:2
[task] | wikipedia [title] | 5. 인벤토리 스크립트 작성 [category] | Guides [rephrased] | 인벤토리 스크립트를 작성하는 과정에서, 클라이언트 UI에 메소(Meso) 수량을 표시하기 위해 `SetMeso()` 함수를 추가해야 합니다. 이 함수는 클라이언트에서만 실행되어야 하므로 실행 공간으로 `[client only]`를 지정하며, 매개변수로 `integer` 타입의 `meso` 값을 수신합니다. 함수 본문에서는 `self.MesoUI.TextComponent.Text` 프로퍼티에 `tostring(meso)`로 변환된 문자열을 대입하여 UI에 메소 값을 갱신합니다. ```lua [client only] void SetM [original] | 7. 새로운 함수 `SetMeso()`를 추가하고 메소UI에 메소 값이 나타날 수 있도록 아래와 같이 작성합니다. ```lua [client only] void SetMeso (integer meso) { self.MesoUI.TextComponent.Text = tostring(meso) } ``` [chunk_id] | Guides:1105:2
[task] | extract_knowledge [title] | 패킷 변조 대비하기 [category] | Guides [rephrased] | # 패킷 변조 방지 및 서버 검증 ## 1. 개념 설명 **패킷(Packet)** 은 메이플스토리 월드에서 서버와 클라이언트 간 데이터를 주고받을 때 사용되는 최소 단위입니다. 함수의 실행 공간(`[server]`, `[client]` 등)에 따라 통신이 발생하며, 이때 함수를 실행할 엔티티, 컴포넌트, 함수 이름, 인자 등의 정보가 패킷에 포함되어 전송됩니다. **패킷 변조(Packet Tampering)** 는 네트워크 통신 중 악의적으로 패킷 데이터를 변경하는 행위입니다. 공격자는 패킷 구조를 분석하여 엔티티 이름, 컴포 [original] | # 학습 과정 소개 서버와 클라이언트가 패킷을 주고 받을 때 데이터 변조가 발생해 크리에이터의 월드에 불편을 초래할 수 있습니다. 패킷 변조를 예방해 쾌적한 월드를 만들기 위해 패킷의 개념과 예방 방법을 알아봅시다. ##### 참고 가이드 * [WorldConfig](/docs/?postId=1101) * [예시로 알아보는 서버 검증](/docs?postId=1084) # 패킷 알아보기 **패킷**은 서버와 클라이언트가 주고받는 데이터의 단위를 말합니다. 메이플스토리 월드에서는 함수의 실행 공간에 따라 클라이언트와 서버가 통 [chunk_id] | Guides:1102:0
[task] | extract_knowledge [title] | 패킷 변조 대비하기 [category] | Guides [rephrased] | # 보안 및 최적화: 패킷 변조 대비하기 메이플스토리 월드에서는 클라이언트가 서버로 보내는 요청을 신뢰하지 않는 것이 보안의 기본 원칙입니다. 클라이언트는 네트워크 패킷을 변조하여 서버 함수를 악용하거나, 동기화되는 데이터를 조작할 수 있습니다. 이를 방지하기 위해 `senderUserId` 검증, `ServiceAuthorityCheck` 활성화, `RestrictedPlayerEntitySync` 활성화 세 가지 기법을 사용해야 합니다. ## 1. senderUserId를 이용한 호출자 검증 `senderUserId`는 서 [original] | **senderUserId**는 서버 함수의 인자로 서버 함수를 호출한 **클라이언트의 userId** 정보를 가지고 있습니다. senderUserId는 서버에서 부여하는 값으로 클라이언트에서 변조되지 않습니다. 예를 들어 월드의 유저A가 자신의 인벤토리에서 특정 아이템을 파기할 때는 아래와 같이 스크립트를 작성할 수 있습니다. 이 스크립트의 경우 다른 클라이언트에서 `RequestDropItem()` 함수를 호출하면, 유저A의 아이템이 삭제될 수 있습니다. ```lua [server] void RequestDropItem(Ent [chunk_id] | Guides:1102:2
[task] | extract_knowledge [title] | 월드 확장해보기 [category] | Guides [rephrased] | # 매칭 인원 및 캐릭터 특성 변경 본 절에서는 슈피겔만 게임 리메이크 월드의 매칭 인원 수를 조정하고, 팀별 캐릭터 물리 특성(크기, 점프)을 수정하는 방법에 대해 설명합니다. ## 1. 매칭 인원 변경하기 매칭 시스템의 최대 인원 수는 데이터셋(Data Set)과 컴포넌트 프로퍼티(Property) 값을 동기화하여 변경해야 합니다. ### API 및 구성 요소 사용법 1. **데이터셋 수정**: `Workspace - MyDesk - 02_InstanceRoom - GameSetting - matchTeamData` 경 [original] | # 매칭 인원 변경하기 데이터 셋과 프로퍼티 값을 변경해 매칭 인원을 변경할 수 있습니다. 1. **Workspace - MyDesk - 02_InstanceRoom - GameSetting - matchTeamData**를 선택합니다. 2. 새로운 행을 추가하고, 데이터를 추가합니다. | PlayerNum | TeamA | TeamB | CloseTargetNum | EnableTargetNum | PlayTime | | --- | --- | --- | --- | --- | --- | | 9 | 3 | 6 [chunk_id] | Guides:1103:0
[task] | distill [title] | 월드 확장해보기 [category] | Guides [rephrased] | # 슈피겔만 게임 리메이크 확장 가이드 ## 1. 중력(Gravity) 설정 및 적용 `DataSet`에 중력 값을 추가하고, `InGameManager`의 `PlayerSetting()` 함수를 수정하여 팀별 중력을 적용합니다. ### 1.1 DataSet 수정 `TeamStatusData` DataSet에 `Gravity` 행을 추가합니다. | Status | TeamA(1) | TeamB(2) | | :--- | :--- | :--- | | Gravity | 0.8 | 1.3 | ### 1.2 PlayerInGameS [original] | DataSet에 새로운 값을 추가하고, **InGameManager** `PlayerSetting()`함수의 코드를 변경해 플레이어에게 중력을 부여할 수 있습니다. 1. **Workspace - MyDesk - 02_InstanceRoom - GameSetting - TeamStatusData**를 선택합니다. 2. 새로운 행에 **Gravity**를 추가합니다. | Status | TeamA(1) | TeamB(2) | | --- | --- | --- | | Gravity | 0.8 | 1.3 | 3. [chunk_id] | Guides:1103:1
[task] | diverse_qa [title] | 월드 확장해보기 [category] | Guides [rephrased] | 질문: InGameObj에 배치해야 하는 3가지 모델의 이름은 무엇이며, 각각의 역할은 무엇인가요? 답변: 배치해야 하는 모델은 ASpawnLocation, BSpawnLocation, Target입니다. ASpawnLocation은 A 팀 멤버가 소환될 위치를, BSpawnLocation은 B팀이 소환될 위치를 지정하며, Target은 메워야 하는 구멍 엔티티입니다. 질문: Target 모델은 몇 개를 배치해야 하나요? 답변: MatchTeamData의 EnableTargetNum 행의 가장 큰 수만큼 배치해야 합니다. 질문: [original] | 1. **Workspace - MyDesk - 02_InstanceRoom - 003_InGame - InGameObj**의 3가지 모델을 배치합니다. * ASpawnLocation: A 팀 멤버가 소환 될 위치로 지정합니다. * BSpawnLocation: B팀이 소환될 위치로 지정합니다. * Target: 메워야하는 구멍 엔티티입니다. 게임을 하는 인원에 맞는 수가 소환되어야 하므로. MatchTeamData의 EnableTargetNum행의 가장 큰 수만큼 배치해야합니다. 2. 새로 만든 맵으로 바로 [chunk_id] | Guides:1103:2
[task] | extract_knowledge [title] | 패킷 변조 대비하기 [category] | Guides [rephrased] | # 패킷 변조 방지 및 보안 최적화 mLua 스크립트에서 클라이언트와 서버 간의 통신을 처리할 때, 패킷 변조(Packet Tampering) 위험을 최소화하기 위한 보안 원칙과 API 사용법을 다룹니다. ## 1. 개념 설명 클라이언트에서 서버로 데이터를 전송할 때 원본 내용을 그대로 신뢰하면, 악의적인 사용자가 클라이언트를 조작하여 데이터(예: 보상 금액, 대상 엔티티 ID)를 변조할 위험이 있습니다. 이를 방지하기 위해 다음과 같은 두 가지 보안 메커니즘을 적용해야 합니다. 1. **실행 제어(Execution Con [original] | 클라이언트에서 서버로 패킷을 보낼 때 내용을 그대로 전송하게 되면, 변조 위험률이 높아집니다. 그러므로 중요한 함수는 실행제어를 **server only**로 설정해 패킷 반복 전송, 인자 값 변경 시도 등을 예방하는 것이 좋습니다. 또한 서버 함수는 클라이언트로부터 온 정보가 변조되지 않았는지 확인해야 합니다. 예를 들어 보상을 지급하는 함수를 작성해야 한다면 **client → server → server only** 함수 순서로 호출되도록 작성하는 것을 권장합니다. 이때 실제 보상을 지급하는 함수는 **server only** [chunk_id] | Guides:1102:1