API и кастомизация
Для тех, кто делает свой сайт, бота или магазин для сервера клана 27, и для тех, кто хочет перекрасить клиентский мод под себя. Свой мод вместо rozb-ui писать не нужно: всё, что сервер отдаёт наружу, — здесь.
API сервера#
Адрес — https://27.rozb.pw/api/v1/. Ответы — JSON в UTF-8, время — секунды Unix, суммы — целые АР.
Без ключа доступно всё публичное: игроки, топы, кланы, кто в сети. С ключом — ваш счёт в банке и счета на оплату игрокам: так магазин на сайте принимает АР. Деньги со счёта игрока списываются только тогда, когда он сам нажмёт «Оплатить» в игре, — ключ не может перевести ни одного АР без его согласия.
Ключ передаётся заголовком:
Authorization: Bearer rozb_…
Ключ — как пароль
Держите ключ только на своём сервере (бэкенде). В браузерный JavaScript, в репозиторий и в чат его не вставляйте. Утёк — сразу отзовите в игре и создайте новый.
Ключи#
В игре: Банк → Ключи API (в моде) или команда /bank api.
- «Новый ключ для личного счёта» — ключ вашего счёта.
- «Новый ключ для казны клана» — есть, если вы лидер или у вашего ранга есть право снимать из казны. Деньги по счетам такого ключа приходят в казну.
- Ключ и секрет подписи вебхуков показываются один раз: окном и сообщением в чат, нажмите на строку — она скопируется. На сервере хранится только отпечаток ключа.
- До 5 ключей на счёт. Отозвать — нажать на ключ в списке (или
/bank api revoke <номер>).
Команды: /bank api, /bank api create, /bank api create clan, /bank api revoke <номер>.
Ошибки и лимиты#
Ошибка — HTTP-код и тело {"error": "<код>", "message": "<текст для людей>"}.
| Код HTTP | Когда |
|---|---|
| 400 | неверные поля запроса (bad_amount, missing_comment, bad_callback…) |
| 401 | нет ключа (no_key) или он неверный / отозван (bad_key) |
| 403 | игрок заблокировал счета от вашего ключа (blocked) |
| 404 | нет такого игрока, клана, счёта (unknown_player, unknown_clan, unknown_invoice) |
| 409 | счёт уже не ждёт оплаты (not_pending) |
| 429 | больше 120 запросов в минуту с одного адреса (rate_limit, заголовок Retry-After) или лимит неоплаченных счетов (too_many_pending) |
| 502, 503 | сервер Minecraft выключен или запускается (server_down, pc_offline, unavailable) — повторите позже |
Сервер работает не круглосуточно: когда он выключен, API отвечает 502. Счета при этом не теряются.
Публичные запросы#
GET /players/{ник} — карточка игрока (как подсказка у ника в чате):
{
"name": "Alice",
"uuid": "f0a8f4ba-…",
"online": true,
"clan": {"tag": "SEV", "name": "Северяне", "rank": "leader"},
"stats": {
"playtime": {"value": 50825, "place": 1},
"player_kills": {"value": 0},
"mob_kills": {"value": 116, "place": 3},
"advancements": {"value": 42, "place": 1},
"deaths": {"value": 5, "place": 4}
},
"first_join": 1792411482,
"first_join_approx": false
}
playtime — в тиках (20 в секунду). place нет, если значение нулевое. clan нет, если игрок не в клане или
клан скрывает состав; rank — leader, deputy, elder, member (нет — игрок скрыл ранг).
first_join_approx: true — игрок заходил раньше, чем сервер начал это записывать: дата приблизительная.
GET /tops/{показатель}?period=all|week&limit=10 — топ (до 50 строк). Показатели: playtime,
player_kills, mob_kills, advancements, deaths. Неделя — разница с суточным снимком семидневной давности;
пока его нет, "pending": true и пустой список.
{"metric": "advancements", "period": "all", "pending": false,
"entries": [{"place": 1, "name": "Alice", "value": 126}, {"place": 2, "name": "Bob", "value": 47}]}
GET /clans — кланы: tag, name, а если клан не скрывает — member_count, leader, created.
GET /clans/{тег} — то же и members (name, rank), если состав открыт.
GET /online — {"count": 3, "max": 20, "players": ["Alice", "Bob", "Carol"]}.
GET /currency — что считается АР: {"name": "АР", "items": ["minecraft:deepslate_diamond_ore", …], "withdraw_item": "…"}.
Счёт ключа#
GET /me — {"account": {"type": "player" | "clan", "name": "Alice"}, "balance": 1250, "key": "7"}.
GET /me/history?limit=20&offset=0 — операции счёта (до 100 за раз), новые первыми:
[{"id": 812, "time": 1792411600, "type": "transfer", "amount": 25, "balance_after": 1250,
"other": "Bob", "note": "Счёт inv_…: Алмазный меч"}]
type: deposit, withdraw, transfer, admin, api; amount со знаком.
Счета на оплату#
POST /invoices — выставить счёт игроку:
{"payer": "Bob", "amount": 25, "comment": "Алмазный меч",
"external_id": "order-1042", "callback_url": "https://shop.example/rozb-hook", "ttl_hours": 24}
| Поле | |
|---|---|
payer |
ник игрока (заходил на сервер) |
amount |
целое, от 1 АР |
comment |
за что, до 100 символов — игрок видит это в игре |
external_id |
необязательно: ваш номер заказа, до 64 символов, вернётся в ответах и вебхуках |
callback_url |
необязательно: куда слать вебхуки (http/https; адреса локальных сетей не принимаются) |
ttl_hours |
необязательно: сколько ждать оплаты, 1–168 часов (по умолчанию 24) |
Ответ 201 — счёт:
{"id": "inv_T2DGDYcQ6fWaNyYs", "status": "pending", "amount": 25, "comment": "Алмазный меч",
"payer": "Bob", "payee": "Alice", "external_id": "order-1042",
"created": 1792411600, "expires": 1792498000, "updated": 1792411600}
status: pending (ждёт), paid, declined (игрок отказался), expired, cancelled (отменили вы).
Игрок в сети сразу видит в чате «Счёт на оплату от Alice: 25 АР — Алмазный меч [Оплатить] [Отказать]», не в
сети — напоминание при входе; все неоплаченные счета — в банке, «Счета на оплату». «Оплатить» открывает окно с
суммой и получателем, деньги переводятся только после нажатия в нём. Игрок может отказаться и заблокировать
отправителя — тогда новые счета от ключей этого счёта получат 403 blocked.
Ограничения: не больше 3 неоплаченных счетов от одного ключа одному игроку и 50 на ключ.
GET /invoices/{id} — счёт (только свой: чужой — 404). DELETE /invoices/{id} — отменить, пока он ждёт.
Вебхуки#
Если у счёта есть callback_url, при оплате, отказе и истечении срока на него приходит POST:
X-Rozb-Event: invoice.paid
X-Rozb-Signature: sha256=<hex HMAC-SHA256 тела секретом ключа>
Content-Type: application/json
{"event": "invoice.paid", "invoice": { …как в GET /invoices/{id}… }}
События: invoice.paid, invoice.declined, invoice.expired. Ответьте 2xx; иначе — ещё две попытки (через
30 секунд и через 5 минут). Перенаправления не выполняются. Вебхук — подсказка: перед выдачей товара сверьте
статус запросом GET /invoices/{id}.
Проверка подписи (Python):
import hmac, hashlib
def valid(body: bytes, header: str, secret: str) -> bool:
good = "sha256=" + hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
return hmac.compare_digest(good, header or "")
Примеры#
curl:
curl https://27.rozb.pw/api/v1/tops/playtime?limit=5
curl -H "Authorization: Bearer $ROZB_KEY" https://27.rozb.pw/api/v1/me
curl -X POST -H "Authorization: Bearer $ROZB_KEY" -H "Content-Type: application/json" \
-d '{"payer":"Bob","amount":25,"comment":"Алмазный меч","external_id":"order-1042"}' \
https://27.rozb.pw/api/v1/invoices
Python (магазин: выставить счёт и дождаться оплаты):
import os, time, requests
API = "https://27.rozb.pw/api/v1"
H = {"Authorization": "Bearer " + os.environ["ROZB_KEY"]}
inv = requests.post(f"{API}/invoices", headers=H, json={
"payer": "Bob", "amount": 25, "comment": "Алмазный меч", "external_id": "order-1042"}).json()
while True:
st = requests.get(f"{API}/invoices/{inv['id']}", headers=H).json()["status"]
if st != "pending":
break
time.sleep(10)
print("итог:", st) # paid — выдать товар
JavaScript (Node 18+, на сервере):
const API = "https://27.rozb.pw/api/v1";
const r = await fetch(`${API}/players/Alice`);
const p = await r.json();
console.log(p.name, p.stats.playtime.value / 20 / 3600, "ч");
Публичные запросы можно делать и прямо из браузера (CORS открыт), но с ключом — только со своего сервера.
Кастомизация мода#
Темы#
Настройки мода → «Тема»: встроенные «Ночь» (по умолчанию), «Графит» и «Лес». Свою тему положите файлом в
config/rozb_ui/themes/<имя>.json или в ресурспак: assets/<пространство>/rozb_ui_themes/<имя>.json. Тема —
только тёмная: цвета текста в окнах задаёт сервер под тёмный фон.
{
"name": "Моя",
"frame": "#0B1120", "chrome": "#0F172A", "toolbar": "#1E293B",
"address": "#0F172A", "address_border": "#334155",
"page": "#111827", "page_edge": "#374151",
"text": "#E2E8F0", "muted": "#94A3B8", "label": "#F8FAFC",
"icon": "#94A3B8", "icon_off": "#475569", "link": "#7DD3FC",
"lock": "#28C840", "check": "#22C55E", "close_hover": "#DC2626",
"nav_hover": "#334155", "nav_down": "#0F172A",
"dots": ["#FF5F57", "#FEBC2E", "#28C840"],
"buttons": {
"normal": {"fill": "#334155", "light": "#475569", "dark": "#1E293B"},
"primary": {"fill": "#166534", "light": "#228B46", "dark": "#14532D"},
"danger": {"fill": "#7F1D1D", "light": "#A62D2D", "dark": "#631616"},
"ghost": {"fill": "#111827", "border": "#475569"},
"field": {"fill": "#0B0F1A", "border": "#475569"},
"off": {"fill": "#1E293B", "border": "#334155"}
}
}
Цвет — #RRGGBB или #AARRGGBB. Всё, что не указано, берётся из «Ночи», поэтому в своей теме достаточно
поменять пару цветов.
Ресурспак#
- Значки шестерёнки настроек и «↻» —
assets/rozb_ui/textures/gui/icon/gear.png(11×11) иreload.png(10×10): белый рисунок на прозрачном фоне, мод сам красит его в цвет темы. - Тексты мода —
assets/rozb_ui/lang/ru_ru.json(ключиrozb_ui.*; полный список — в файле внутриrozb-ui-*.jar). Тексты окон присылает сервер, ресурспаком их не поменять. - Плитки «Главной» рисуются предметами — их внешний вид меняется обычными текстурами предметов.
- Темы — папка
rozb_ui_themes(см. выше).
Свои плитки «Главной»#
Настройки мода → «Свои плитки «Главной»…»: название, команда (как в чате, например spawn или /warp шахта) и
значок — id предмета (minecraft:compass). До 12 плиток, отмечены голубой точкой. Порядок всех плиток, и своих, и
серверных, меняется перетаскиванием прямо на «Главной». Всё хранится в config/rozb-ui.json только у вас.