BuzzBuild-Coupon — 설정
서버 운영자를 위한 설정 참조입니다. 아래 표의 기본값은 배포 리소스 기준이며, 코드에서 보정하거나 무시하는 값은 설명에 구분했습니다.
설정 파일과 저장 위치
섹션 제목: “설정 파일과 저장 위치”| 파일·저장소 | 용도 | 적용 |
|---|---|---|
서버 기준 plugins/BuzzBuild-Coupon/config.yml | 쿨다운, 생성 기본값, 한도, 연동, 메시지, 사운드 | /bbcoupon reload |
서버 기준 plugins/BuzzBuild-Coupon/gui.yml | Paper 목록·보상 상자 레이아웃과 텍스트 | GUI를 다시 열 때 읽음 |
MariaDB bb_coupon_coupons, bb_coupon_uses | 쿠폰 정의와 사용 기록 | 관리자 기능에서 저장 |
별도 Fabric 사용자 설정 파일은 없습니다. DB 연결과 와이어 채널은 Framework가 관리하며 Coupon 설정으로 변경하지 않습니다. 보상은 DB의 rewards_json JSON 배열로 저장됩니다. 일반 운영에서는 DB를 직접 편집하지 않고 명령·상자 GUI를 사용합니다.
config.yml: 동작 설정
섹션 제목: “config.yml: 동작 설정”| 키 | 타입 | 기본값 | 설명 |
|---|---|---|---|
redeem.cooldown-seconds | 정수 | 3 | 플레이어별 재시도 간격(초). 최솟값 0, 0은 비활성. 비어 있지 않은 실패 조회에도 적용 |
redeem.normalize-codes | 불리언 | true | true: trim 후 공백 제거·대문자 변환. false: trim만 수행 |
defaults.max-uses | 정수 | 1 | CLI 생성 시 -max 생략값. 최솟값 0, 0은 무제한 |
defaults.per-player | 정수 | 1 | CLI 생성 시 -per 생략값. 최솟값 0, 0은 무제한 |
defaults.fallback-message-reward | 문자열 | "쿠폰이 적용되었습니다!" | 보상이 없을 때 추가할 메시지. 비어 있으면 코드 기본 문구 사용 |
limits.max-batch | 정수 | 50 | 서버 생성 요청의 배치 개수 상한. 최솟값 1. CLI 배치 생성 명령 없음 |
limits.max-item-rewards | 정수 | 27 | 서버 생성 요청·상자 저장 시 아이템 보상 항목 수 상한. 최솟값 1 |
limits.random-code-length | 정수 | 8 | 난수 코드 길이. 4~32로 보정 |
nexo.blank-item-id | 문자열 | "blank" | 하단 GUI 베이스 아이템 ID. 빈 문자열이면 Nexo 조회 생략. nexo: 접두사 허용 |
nexo.fallback-material | 문자열 | "GRAY_STAINED_GLASS_PANE" | Nexo 미설치·조회 실패 시 대체 Material. 잘못된 값이나 AIR이면 기본 회색 유리판 |
integrations.vault-rewards | 불리언 | true | Vault 보상 지급 스위치. false이면 해당 보상 생략·부분 실패 처리 |
구키 redeem-cooldown-seconds, normalize-codes를 읽는 fallback이 있으며 새 redeem.* 키를 우선합니다. 새 문서는 중첩 키를 사용합니다. 설정을 바꿔도 기존 DB의 정규화 코드·한도·만료를 다시 계산하지 않습니다.
limits.max-item-rewards를 높여도 Paper 보상 상자는 0~26번 슬롯만 편집합니다. 낮추면 상자 저장 시 상한을 넘는 아이템 항목은 저장되지 않습니다. Fabric 생성 화면은 아이템 27개·배치 50개 상한을 자체 적용하므로 서버 상한 증가가 화면에 반영되지 않습니다. Fabric 생성 화면의 한도 초깃값 1과 메시지도 서버 defaults.*를 읽지 않습니다.
config.yml: 메시지
섹션 제목: “config.yml: 메시지”모두 문자열입니다. 기본값에 들어 있는 상황별 문구와 치환자를 표에 그대로 기록했습니다. 치환자는 전역 변수가 아니라 각 호출 지점에서만 제공됩니다. %player%는 설정 주석에는 있으나 현재 메시지 치환 호출에서 확인되지 않았습니다.
| 키 | 타입 | 기본값 | 설명 |
|---|---|---|---|
messages.redeem-success | 문자열 | "&a쿠폰을 사용했습니다!" | 해당 상황의 피드백 문구 |
messages.redeem-empty-code | 문자열 | "&c쿠폰 코드를 입력하세요." | 해당 상황의 피드백 문구 |
messages.redeem-not-ready | 문자열 | "&c쿠폰 시스템이 준비되지 않았습니다." | 해당 상황의 피드백 문구 |
messages.redeem-not-found | 문자열 | "&c존재하지 않는 쿠폰 코드입니다." | 해당 상황의 피드백 문구 |
messages.redeem-disabled | 문자열 | "&c비활성화된 쿠폰입니다." | 해당 상황의 피드백 문구 |
messages.redeem-expired | 문자열 | "&c만료된 쿠폰입니다." | 해당 상황의 피드백 문구 |
messages.redeem-global-limit | 문자열 | "&c쿠폰 사용 한도가 모두 소진되었습니다." | 해당 상황의 피드백 문구 |
messages.redeem-player-limit | 문자열 | "&c이미 사용한 쿠폰입니다." | 해당 상황의 피드백 문구 |
messages.redeem-rate-limited | 문자열 | "&c너무 빠르게 시도했습니다. 잠시 후 다시 시도하세요." | 해당 상황의 피드백 문구 |
messages.redeem-reward-partial | 문자열 | "&e쿠폰은 사용됐으나 보상 일부에 실패했습니다. 관리자에게 문의하세요." | 해당 상황의 피드백 문구 |
messages.inventory-full-drop | 문자열 | "&e인벤토리가 가득 차 아이템 일부를 바닥에 드롭했습니다." | 해당 상황의 피드백 문구 |
messages.no-permission | 문자열 | "&c권한이 없습니다." | 해당 상황의 피드백 문구 |
messages.player-only | 문자열 | "&c이 명령어는 플레이어만 사용할 수 있습니다." | 해당 상황의 피드백 문구 |
messages.invalid-request | 문자열 | "&c잘못된 요청입니다." | 해당 상황의 피드백 문구 |
messages.coupon-not-found | 문자열 | "&c쿠폰을 찾을 수 없습니다: %code%" | 해당 상황의 피드백 문구. 호출 지점 치환: %code% |
messages.coupon-not-found-short | 문자열 | "&c쿠폰을 찾을 수 없습니다." | 해당 상황의 피드백 문구 |
messages.create-ok | 문자열 | "&a쿠폰 생성됨: &f%code%&7 (max=%detail%)" | 해당 상황의 피드백 문구. 호출 지점 치환: %code%, %detail% |
messages.create-fail-duplicate | 문자열 | "&c쿠폰 생성 실패 — 코드가 비었거나 이미 존재합니다." | 해당 상황의 피드백 문구 |
messages.create-usage | 문자열 | "&c사용법: /bbcoupon create <코드> [-max N] [-per N] [-expire 시간] [-memo …] [-cmd …] [-vault N] [-msg …]" | 해당 상황의 피드백 문구 |
messages.create-hint-reward | 문자열 | "&7생성 후 보상 상자가 열립니다. 아이템만 수정: &f/bbcoupon reward <코드>" | 해당 상황의 피드백 문구 |
messages.reward-open-hint | 문자열 | "&e상자에 보상 아이템을 넣고 닫으세요. &7(하단 「목록으로」로도 저장)" | 해당 상황의 피드백 문구 |
messages.reward-saved | 문자열 | "&a쿠폰 보상을 저장했습니다. &7(아이템 %count%개)" | 해당 상황의 피드백 문구. 호출 지점 치환: %count% |
messages.reward-usage | 문자열 | "&c사용법: /bbcoupon reward <코드>" | 해당 상황의 피드백 문구 |
messages.vault-prompt-title | 문자열 | "&e[%code%] Vault 금액을 채팅에 입력하세요." | 해당 상황의 피드백 문구. 호출 지점 치환: %code% |
messages.vault-prompt-hint | 문자열 | "&7현재: &f%detail% &8│ &a숫자 &7저장 · &c0 &7제거 · &e웅크리기 &7취소" | 해당 상황의 피드백 문구. 호출 지점 치환: %detail% |
messages.vault-set | 문자열 | "&aVault 보상을 설정했습니다: &f%amount%" | 해당 상황의 피드백 문구. 호출 지점 치환: %amount% |
messages.vault-removed | 문자열 | "&eVault 보상을 제거했습니다." | 해당 상황의 피드백 문구 |
messages.vault-cancelled | 문자열 | "&eVault 금액 입력을 취소했습니다." | 해당 상황의 피드백 문구 |
messages.vault-bad-number | 문자열 | "&c숫자가 아닙니다. 다시 입력하거나 웅크리기로 취소하세요." | 해당 상황의 피드백 문구 |
messages.vault-usage | 문자열 | "&c사용법: /bbcoupon vault <코드> <금액> &7(0이면 제거)" | 해당 상황의 피드백 문구 |
messages.vault-cli-set | 문자열 | "&aVault 보상 설정: &f%code% &7→ &f%amount%" | 해당 상황의 피드백 문구. 호출 지점 치환: %code%, %amount% |
messages.vault-cli-removed | 문자열 | "&eVault 보상을 제거했습니다: &f%code%" | 해당 상황의 피드백 문구. 호출 지점 치환: %code% |
messages.enabled | 문자열 | "&a쿠폰을 활성화했습니다." | 해당 상황의 피드백 문구 |
messages.disabled | 문자열 | "&e쿠폰을 비활성화했습니다." | 해당 상황의 피드백 문구 |
messages.list-empty | 문자열 | "&7등록된 쿠폰이 없습니다." | 해당 상황의 피드백 문구 |
messages.admin-reload | 문자열 | "&a[BB-Coupon] 설정을 다시 불러왔습니다." | 해당 상황의 피드백 문구 |
messages.hand-empty | 문자열 | "&c메인 핸드에 아이템이 없습니다." | 해당 상황의 피드백 문구 |
messages.hand-added | 문자열 | "&a아이템을 추가했습니다: %detail%" | 해당 상황의 피드백 문구. 호출 지점 치환: %detail% |
직접 메시지 전송은 & 색코드를 해석하고 빈 문자열을 보내지 않습니다. 다만 저장소 조회 실패 메시지는 빈 설정이면 기본 오류 문구로 돌아가는 분기가 있습니다. Fabric·쿠폰 사용 결과로 전달되는 메시지는 색코드를 제거한 뒤 성공/실패 색을 별도로 적용하므로 모든 경로에 동일한 색 설정이 적용되지는 않습니다. 도움말, 정보 출력, 일부 숫자 검증 오류와 Fabric 화면 문구는 코드에 고정되어 있습니다.
messages.create-ok의 %detail% 값 자체가 max=... per=...로 시작하여 기본 문구에서 max=max=...처럼 중복 표시될 수 있습니다.
config.yml: 사운드
섹션 제목: “config.yml: 사운드”| 키 | 타입 | 기본값 | 설명 |
|---|---|---|---|
sounds.redeem-success.key | 문자열 | "" | 사운드 키. 빈 문자열은 비활성 |
sounds.redeem-success.volume | 실수 | 1 | 볼륨. 별도 범위 보정 없음 |
sounds.redeem-success.pitch | 실수 | 1 | 피치. 별도 범위 보정 없음 |
sounds.redeem-fail.key | 문자열 | "" | 사운드 키. 빈 문자열은 비활성 |
sounds.redeem-fail.volume | 실수 | 1 | 볼륨. 별도 범위 보정 없음 |
sounds.redeem-fail.pitch | 실수 | 1 | 피치. 별도 범위 보정 없음 |
sounds.reward-saved.key | 문자열 | "" | 사운드 키. 빈 문자열은 비활성 |
sounds.reward-saved.volume | 실수 | 1 | 볼륨. 별도 범위 보정 없음 |
sounds.reward-saved.pitch | 실수 | 1 | 피치. 별도 범위 보정 없음 |
키가 비어 있으면 소리를 재생하지 않습니다. 보상 일부 실패는 사용 자체를 성공으로 반환하여 redeem-success 사운드 경로를 사용합니다. 사운드 키의 실제 재생 여부는 게임에서 확인해야 합니다.
gui.yml: 레이아웃과 텍스트
섹션 제목: “gui.yml: 레이아웃과 텍스트”슬롯 번호는 0부터 시작합니다. 아래 배열은 YAML에서도 사용할 수 있는 인라인 배열 표기입니다. 이름·설명은 MiniMessage 또는 레거시 색코드를 처리하지만, 별도의 Nexo 글리프 태그 resolver는 코드에 없습니다.
| 키 | 타입 | 기본값 | 설명 |
|---|---|---|---|
list.title-format | 문자열 | "쿠폰 목록 · %page%" | 목록 제목. %page% 치환 |
list.rows | 정수 | 6 | 목록 행 수. 생성 크기는 9~54칸으로 보정 |
list.content-slots.start | 정수 | 0 | 목록 시작 슬롯(0부터). 음수·버튼 겹침을 피할 것 |
list.content-slots.end | 정수 | 44 | 목록 마지막 슬롯. 두 값 차이+1이 페이지 크기 |
list.bottom.filler-slots | 배열 | [46,47,48,50,51,52] | 목록 하단 채움 슬롯 목록 |
list.bottom.previous-page.slot | 정수 | 45 | 이전 페이지 버튼 슬롯 |
list.bottom.previous-page.name | 문자열 | "<red>이전 페이지" | 이전 버튼 이름. %page% 치환 |
list.bottom.previous-page.lore | 배열 | ["<gray>현재 %page% 페이지"] | 이전 버튼 설명 줄 목록. %page% 치환 |
list.bottom.next-page.slot | 정수 | 53 | 다음 페이지 버튼 슬롯 |
list.bottom.next-page.name | 문자열 | "<aqua>다음 페이지" | 다음 버튼 이름. %page% 치환 |
list.bottom.next-page.lore | 배열 | ["<gray>현재 %page% 페이지"] | 다음 버튼 설명 줄 목록. %page% 치환 |
list.bottom.info-when-exists.slot | 정수 | 49 | 쿠폰이 있을 때 정보 아이콘 슬롯 |
list.bottom.info-when-exists.name | 문자열 | "<#d39a70>%count%개의 쿠폰" | 쿠폰이 있을 때 이름. %count%, %page% 치환 |
list.bottom.info-when-exists.lore | 배열 | ["<white>좌클릭 — 정보","<white>쉬프트+좌클릭 — 보상(아이템)","<white>쉬프트+우클릭 — Vault 금액","<white>우클릭 — 활성/비활성 토글"," ","<gray>/bbcoupon create <코드>"] | 쿠폰이 있을 때 설명 줄 목록. %count%, %page% 치환 |
list.bottom.info-when-empty.slot | 정수 | 49 | 쿠폰이 없을 때 정보 아이콘 슬롯 |
list.bottom.info-when-empty.name | 문자열 | "<#d39a70>등록된 쿠폰이 없습니다" | 쿠폰이 없을 때 이름. %count%, %page% 치환 |
list.bottom.info-when-empty.lore | 배열 | ["<gray>/bbcoupon create <코드> 로 생성하세요"] | 쿠폰이 없을 때 설명 줄 목록. %count%, %page% 치환 |
list.icon-lore | 배열 | [" ","<green>│ <white>좌클릭 — 정보","<gold>│ <white>쉬프트+좌클릭 — 아이템 보상","<aqua>│ <white>쉬프트+우클릭 — Vault 금액","<red>│ <white>우클릭 — 활성/비활성"," ","<gray>상태: %status% · 사용 %uses%","<gray>Vault: %vault% · 아이템 %items_count%개","<dark_gray>%memo%"] | 쿠폰 아이콘 설명. %status%, %uses%, %vault%, %items_count%, %memo% 치환 |
set.title-format | 문자열 | "쿠폰 보상 · %name%" | 보상 상자 제목. %name%을 쿠폰 표시 코드로 치환 |
set.rows | 정수 | 4 | 보상 상자 행 수. 생성 크기는 36~54칸으로 보정. 보상 영역은 27칸 고정 |
set.content-slots.start | 정수 | 0 | 리소스에만 존재. 구현에서 읽지 않음 |
set.content-slots.end | 정수 | 26 | 리소스에만 존재. 구현에서 읽지 않음 |
set.bottom-filler-slots | 배열 | [27,28,29,33,34,35] | 보상 상자 하단 채움 슬롯 목록 |
set.menu-button.slots | 배열 | [30,31,32] | 저장 후 목록으로 돌아가는 버튼 슬롯 목록 |
set.menu-button.name | 문자열 | "<#a9cf70>목록으로" | 목록으로 버튼 이름 |
set.menu-button.lore | 배열 | ["<gray>저장 후 쿠폰 목록으로 돌아갑니다","<gray>닫기만 해도 아이템 보상이 저장됩니다"] | 목록으로 버튼 설명 줄 목록 |
set.content-slots.start/end는 리소스에만 있고 구현은 CONTENT_SLOTS = 27을 사용합니다. 버튼·채움 슬롯이 보상 영역을 덮지 않도록 기본 배치를 유지합니다. 목록은 내용 시작/끝 값을 별도로 안전 보정하지 않으므로 인벤토리 크기 안에서 하단 버튼과 겹치지 않게 배치합니다. 기본 GUI 리소스를 유지한 채 제목·문구만 바꾸는 방식이 가장 단순합니다.
최소 설정 예시
섹션 제목: “최소 설정 예시”다음은 기본 파일에서 바꿀 동작 키만 보여주는 YAML 예시입니다. 생성된 파일의 메시지·사운드·GUI 설정을 모두 삭제하라는 뜻이 아닙니다. Vault 금액 보상을 사용하지 않는 예시입니다.
redeem: cooldown-seconds: 3 normalize-codes: truedefaults: max-uses: 1 per-player: 1 fallback-message-reward: "쿠폰이 적용되었습니다!"limits: max-batch: 50 max-item-rewards: 27 random-code-length: 8nexo: blank-item-id: "" fallback-material: GRAY_STAINED_GLASS_PANEintegrations: vault-rewards: false이 예시에서는 기존 vault 보상도 생략되고 부분 실패로 처리됩니다. 금액 보상을 사용하는 서버는 Economy 연동을 확인한 뒤 true로 설정합니다. 저장 후 /bbcoupon reload를 실행하고 GUI는 다시 엽니다. DB·Vault 서비스 재초기화는 수행하지 않습니다.
확인 범위
섹션 제목: “확인 범위”2026-10-05 기준 기본 YAML의 모든 말단 키와 설정 로더·GUI 소비 코드를 대조했습니다. 게임 내 동작은 미검증입니다.