Скрипт это обычный Python 3-файл в папке со скриптами. Имена ниже уже существуют, когда скрипт начинает работать: клиент кладёт их туда сам, а импортировать их не нужно и нельзя.
| Имя | Тип | Назначение |
|---|---|---|
Module / module | конструктор | Создать модуль клиента |
Hud / HUD | конструктор | HUD-элемент: Hud("Имя", width=..., height=...) |
Esp / ESP | конструктор | Элемент ESP: Esp("esp.mybox", targets=["players"]) |
Storage | конструктор | JSON-база: Storage("myscript") |
Shader | конструктор | Свой шейдер: Shader("glow", GLSL) |
Command | конструктор | Команда чата: @Command("hello") |
Checkbox / checkbox | конструктор | Настройка-галочка |
Slider / slider | конструктор | Настройка-слайдер |
Mode / mode | конструктор | Настройка с выбором одного значения |
Select / select | конструктор | Настройка-мультивыбор |
Button / button | конструктор | Настройка-кнопка |
Range | конструктор | Настройка-диапазон (двойной слайдер). Строчного range нет, это builtin |
ColorSetting / colorsetting | конструктор | Настройка-цвет |
Bind / bind | конструктор | Настройка-клавиша |
TextSetting / textsetting | конструктор | Настройка-строка (поле ввода) |
TimeSetting / timesetting | конструктор | Настройка-время (часы, минуты, секунды) |
Gradient / gradient | конструктор | Настройка-градиент из двух цветов |
PositionSetting / positionsetting | конструктор | Настройка-точка на площадке |
Bezier / bezier | конструктор | Настройка-кривая плавности |
Blocks / blocks | конструктор | Настройка-сетка блоков |
Info / info | конструктор | Заголовок секции, значения не хранит |
Color / color | конструктор | Цвет: Color(r, g, b[, a]), Color.from_hex(...) |
ColorRGBA | класс | Готовые цвета: WHITE, BLACK, RED и другие |
border | функция | border(r) скругляет все углы |
border4 | функция | border4(tl, tr, br, bl) задаёт скругление по углам |
events | объект | Подписка на события |
client | объект | API клиента: сообщения, модули, шрифты, пути |
modules | объект | Ярлык для client.modules |
settings | объект | Ярлык для client.settings |
messages | объект | Ярлык для client.messages |
ui | объект | Ярлык для client.ui (курсор, border) |
hud / HUD / Hud | объект | HUD-элементы |
island / dynamic_island / DynamicIsland | объект | Менеджер Dynamic Island: find, all, mine, remove |
IslandStatus / island_status | конструктор | Создать статус острова, как Module(...) для модулей |
music | объект | Что играет на компьютере: трек, обложка, текст песни, управление |
sound / audio | объект | Свои звуки: wav, mp3 и ogg из папки скрипта или по ссылке |
screen | декоратор | Экран или меню с лейаутом |
raw_screen / screen_raw | декоратор | Экран с голым рисованием |
paths | объект | Пути: root() и game_dir(), scripts(), runtime() |
fonts / font | объект | Шрифты: font("medium", 8) |
assets / image / texture | объект и функции | Картинки, шрифты, ресурсы клиента |
mc | обёртка | MinecraftClient: mc.player, mc.world, mc.options |
jimport | функция | jimport("net.minecraft.entity.LivingEntity") |
is_instance / isInstance | функция | Проверка класса: is_instance(packet, "net...PlayerMoveC2SPacket") |
wrap / unwrap | функция | Ручная обёртка объекта игры. Объекты из API готовы и без неё |
world | объект | Мир: сущности, игроки, цель |
newton | объект | Newton: ходьба, полёт, копка, области |
command | декоратор | Своя команда чата: @command("hello") |
commands | объект | Команды: add, remove, exists, all, run, prefix |
notify | объект | Уведомления клиента: island, crosshair, item |
inventory / inv | объект | Инвентарь: поиск, счётчики, перекладывание |
effects / buffs | объект | Баффы и дебаффы: список, время, иконки |
profile / account / user | объект | Аккаунт игрока: ник, uid, роль, подписка, аватарка |
menu | объект | Меню клиента: тип, анимация, координаты панелей |
theme / colors | объект | Цвета текущей темы клиента |
keys | объект | Клавиши и курсор: коды, зажатые клавиши, позиция мыши |
skins / skin | объект | Скин, плащ и элитра игроков глазами твоего клиента |
lang / tr | объект | Переводы скрипта: ключ вместо строки, язык подставит клиент |
esp | объект | Свои элементы ESP: цели отбирает клиент, скрипт рисует |
target | объект | Выбор цели правилами клиента |
funtime / ft | объект | Данные FunTime: ивенты, шахты, баны |
aura | объект | Aura: свои режимы ротации |
rotations | объект | Ротации вне Aura |
render3d / render_3d | объект | 3D-рендер |
shader / shaders | объект | Свои шейдеры GLSL |
Timer | класс | Таймер |
storage | объект | JSON-хранилище |
vec | объект | 3D-математика |
print | функция | Лог клиента (latest.log), а не чат |
mod = Module("MyModule", "Combat") # имя, категория
mod.setDesc("Описание модуля") # возвращает сам модуль, можно цепочкойКатегории (регистр не важен): Combat, Movement, Visuals, Player, Other. Неизвестная категория превращается в Other.
| Метод | Возврат | Описание |
|---|---|---|
isEnabled() | bool | Включён ли модуль |
setEnabled(bool) | сам модуль | Включить или выключить |
toggle() | сам модуль | Переключить |
getName() | str | Имя |
getCategory() | str | Категория. У своего модуля строка как передал ("Combat"), у чужого имя enum ("COMBAT") |
getModule() | Module | Модуль, который переключили |
getDesc() / setDesc(str) | str / сам модуль | Описание |
getKey() / setKey(int) | int / сам модуль | Бинд, код клавиши по GLFW |
getKeyName() | str | Имя клавиши бинда |
settings() | список | Настройки модуля: у каждой можно спросить тип и значение |
@events.module_toggled
def on_toggle(event):
if event.getModule().getName() == "MyModule":
client.msg("включён" if event.isState() else "выключен")Работа с чужими модулями:
client.modules.all() # список всех PyModule
client.modules.find("Aura") # PyModule или None, если модуля нет
client.modules.require("Aura") # PyModule или ValueError, если модуля нет
client.modules.enabled("Aura") # bool (False, если модуля нет)
client.modules.enable("Aura") # идёт через require, значит ValueError, если модуля нет
client.modules.disable("Aura")
client.modules.toggle("Aura")
client.find("Aura") # то же, что modules.find: PyModule или None
# настройка чужого модуля: имя это внутренний ключ, а не подпись из меню
client.find("Aura", "modules.settings.aura.attackDistance")Настройка создаётся с привязкой к цели первым аргументом, это модуль или HUD-элемент. Все методы настройки возвращают саму настройку, так что их пишут цепочкой.
mod = Module("Demo", "Visuals")
enabled = Checkbox(mod, "Enabled")
speed = Slider(mod, "Speed").min(1).max(10).step(0.5).set(5).suffix(" м/с")
target = Mode(mod, "Target").add("Head").add("Body").select("Head")
filters = Select(mod, "Filters").add("Players").add("Mobs").select("Players").min(1).draggable()
btn = Button(mod, "Run").action(lambda: client.msg("клик"))
rng = Range(mod, "Range").min(0).max(20).step(1).first(3).second(7)
col = ColorSetting(mod, "Color").color(255, 0, 0).alpha(True)
hotkey = Bind(mod, "Hotkey").set("G")
nick = TextSetting(mod, "Nick").maxLength(16).set("Steve")
pause = TimeSetting(mod, "Pause").units("minutes", "seconds").set(90)
grad = Gradient(mod, "Gradient").set(Color(255, 0, 90), Color(90, 0, 255))
offset = PositionSetting(mod, "Offset").bounds(-1, -1, 1, 1).set(0, 0)
curve = Bezier(mod, "Easing").start(0.2, 0.0).end(0.8, 1.0)
blocks = Blocks(mod, "Blocks").select("obsidian")
Info(mod, "Заголовок секции")| Тип | Конструктор | Методы настройки | Чтение |
|---|---|---|---|
Checkbox | (target, name) | set(bool) | get() -> bool, toggle() |
Slider | (target, name) | min(n) max(n) step(n) set(n) suffix(s) | get() -> float, getMin(), getMax(), getStep() |
Mode | (target, name) | add(name), select(name) | get() -> str |
Select | (target, name) | add(name), select(name), min(int), draggable() | isSelected(name), getSelected() -> [str], getValues() -> [str] |
Button | (target, name) | action(fn) | click() |
Range | (target, name) | min(n) max(n) step(n) first(n) second(n) | get() -> [float, float], getFirst(), getSecond(), getMin(), getMax(), getStep() |
ColorSetting | (target, name) | color(ColorRGBA), color(r, g, b[, a]), alpha(bool) | get() -> ColorRGBA, hasAlpha() |
Bind | (target, name) | set(code или "G"), clear() | get() -> int, name() -> str, isKey(code или "G"), isSet() |
TextSetting | (target, name) | set(str), maxLength(int), numberOnly(bool) | get() -> str, isEmpty() |
TimeSetting | (target, name) | set(seconds), units("hours", "minutes", "seconds"), unit(name, bool), maxHours(int), maxMinutes(int) | get() -> int (секунды), millis(), ticks(), formatted(), hours(), minutes(), seconds() |
Gradient | (target, name) | set(c1, c2), first(c), second(c), alpha(bool) | getFirst(), getSecond(), at(0..1) -> ColorRGBA, hasAlpha() |
PositionSetting | (target, name) | set(x, y), x(n), y(n), bounds(minX, minY, maxX, maxY) | get() -> [float, float], getX(), getY(), getMinX(), getMaxX(), getMinY(), getMaxY() |
Bezier | (target, name) | start(x, y), end(x, y) | ease(0..1) -> float, interpolate(from, to, 0..1), getStart(), getEnd() |
Blocks | (target, name) | select(id), toggle(id), allow(id), allowAll(), allowItem(id), allowAllItems() | getSelected() -> [str], isSelected(id), count() |
Info | (target, name) | level(int), splitted(), centered() | значения нет |
Значения по умолчанию: Slider это min 1, max 10, value 5, step 1; Range это min 1, max 10, first 3, second 7, step 1; Checkbox выключен; ColorSetting белый с альфой; у Mode выбран первый добавленный вариант.
Как разобрать чужие настройки. mod.settings() отдаёт список настроек модуля. Метод type() возвращает одно из: "boolean", "slider", "range", "mode", "select", "color", "button", "bind", "text", "time", "gradient", "position", "bezier", "blocks", "info", "other".
| Группа | Методы |
|---|---|
| общее | name() (подпись из меню), rawName() (постоянное имя), visible(), type() |
| boolean | boolGet(), boolSet(b), boolToggle() |
| slider | numGet(), numSet(v), numMin(), numMax(), numStep() |
| mode | optionLabels(), options(), modeIndex(), modeSelect(i) |
| select | optionLabels(), selOn(i), selToggle(i), selCount() |
| color | colorGet(), colorSet(c) |
| button | click() |
| bind | bindKey(), bindName(), bindSet(key) |
| text | textGet(), textSet(v) |
| time | timeGet(), timeSet(seconds), timeMillis(), timeTicks(), timeFormatted() |
| gradient | gradientFirst(), gradientSecond(), gradientSet(c1, c2) |
| position | posX(), posY(), posSet(x, y) |
| bezier | bezierEase(0..1) |
| blocks | blocksSelected(), blockSelected(id), blockToggle(id) |
Подписаться можно тремя способами, имя события нечувствительно к регистру:
@events.tick
def on_tick(event): ...
events.tick(on_tick)
events.tick.on(on_tick)
events.getEvent("tick").on(on_tick)Обработчик получает сам объект события, зови его настоящие методы. Отменяемые события поддерживают event.cancel() и event.isCancelled().
| Событие | Отменяемо | Методы события |
|---|---|---|
tick | нет | Методов нет. Каждый тик игрока |
motion | да | getX/getY/getZ(), setX/setY/setZ(), getYaw()/setYaw(), getPitch()/setPitch(), isOnGround()/setOnGround(), isSneaking()/setSneaking(), isSprinting()/setSprinting() |
input | нет | getForward()/setForward(), getStrafe()/setStrafe(), isJump()/setJump(), isSneak()/setSneak(), isSprint()/setSprint(), getSneakSlowDownMultiplier()/setSneakSlowDownMultiplier(), setYaw(yaw), setYaw(yaw, direction), setYawSmooth(yaw), setYawSmooth(yaw, direction) |
move_post | нет | getSpeed(), getMovementInput() |
travel_post | нет | getOldVelocity()/setOldVelocity() |
slowdown | да | Методов нет. Замедление при еде или щите |
attack | да | getEntity() |
after_attack | да | getEntity() |
block_break | да | getBlockPos() |
block_place | нет | getPlacePos(), getHitPos(), getSide(), getHand(), getStack() |
entity_jump | да | getEntity(), это LivingEntity |
pickup | нет | getEntity(), getItemStack(), getCount() |
firework | нет | getEntity(), getVelocity()/setVelocity(), getRocketEntity() |
rotate_camera | да | getDeltaYaw()/setDeltaYaw(), getDeltaPitch()/setDeltaPitch() |
send_message | да | getMessage()/setMessage(), исходящее сообщение в чат |
world_change | нет | Методов нет. Смена мира |
send_packet | да | getPacket()/setPacket() |
receive_packet | да | getPacket() |
connect | нет | getAddress(), getInfo(), getCookieStorage() |
render_2d | нет | getContext() отдаёт холст для рисования, getTickDelta() |
pre_render_2d | нет | getContext(), getTickDelta(), зовётся до HUD клиента |
render_3d | нет | getMatrices(), getCamera(), getPositionMatrix(), getProjectionMatrix(), getTickDelta() |
pre_render_3d | нет | Поля те же, что у render_3d. Мир ещё не нарисован: рисунок прячется за блоками |
module_toggled | нет | getModule() отдаёт PyModule, isState() |
newton_started | нет | getProcess(), имя задачи Newton |
newton_path | нет | getProcess(), getSteps() |
newton_node | нет | getProcess(), getX(), getY(), getZ(), getStep(), getSteps() |
newton_finished | нет | getProcess() |
newton_failed | нет | getProcess(), getReason() |
game_tick | нет | Методов нет. Тик игры, идёт и вне мира |
tick_end | нет | Методов нет. Конец тика игрока, движение уже посчитано |
keep_sprint | да | Методов нет. Отмена оставляет разгон при ударе |
trace | да | getYaw()/setYaw(), getPitch()/setPitch(), отмена пересчитывает луч по этим углам |
collision_shape | да | getState(), getPos(), getShape()/setShape(), отмена убирает столкновение блока |
sound | нет | getSound() |
entity_death | нет | getEntity(), getSource(), getKillerEntity() |
finish_eat | нет | getUser(), getStack() |
effect_added | нет | getEffect(), getEntity(), isUpgraded() |
effect_removed | нет | getEffect(), getEntity(), isExpired() |
start_break_block | да | getBlockPos() |
break_totem | нет | getEntity(), getStack() |
set_cooldown | нет | getCooldown()/setCooldown(), getCooldownGroup() |
close_screen | нет | getScreen() |
container_click | нет | getX(), getY(), getButton() |
hand_render | да | getArm(), getSwingProgress(), getEquipProgress(), getItemStack(), getMatrices() |
camera_update | нет | getCamera(), getFocusedEntity(), isThirdPerson(), isInverseView(), getTickDelta() |
game_render | нет | Методов нет. Кадр игры, приходит и в меню |
notification | нет | getStyle(), getType(), getTitle(), getText() |
| Метод | Описание |
|---|---|
client.msg(text) | Сообщение в чат |
client.warn(text) | Предупреждение в чат |
client.error(text) | Ошибка в чат |
client.overlay(text) | Текст над хотбаром |
client.chat(text) / client.say(text) | Сказать в чат ОТ ИМЕНИ ИГРОКА: строка уходит на сервер. Со слэша - командой |
client.command(line) / client.cmd(line) | Команда серверу, слэш в начале не обязателен |
client.reconnect(delay=1.5) | Перезайти на тот же сервер через delay секунд |
client.join(address, delay=1.5) | Зайти на сервер по адресу: play.example.su или play.example.su:25566. False, если адрес не разобрался |
client.disconnect() | Выйти в меню серверов |
client.server() | Адрес сервера или None в одиночной игре |
client.gameDir() / client.game_dir() | Папка клиента .minecraft/Rockstar (в ней scripts/ и runtime/), а НЕ папка игры. То же, что paths.root() |
client.menu_opened() | Открыто ли меню клиента |
client.cursor(name) | Курсор: arrow/default, hand/pointer, text/ibeam, crosshair, hresize/horizontal, vresize/vertical, block/notallowed, resize/resizeall |
client.font_width(weight, size, text) | Ширина текста в пикселях |
client.font_height(weight, size) | Высота строки |
client.find(module) | Найти модуль по имени, вернёт PyModule или None |
client.find(module, setting) | Найти настройку чужого модуля, вернёт настройку или None |
client.modules | all(), find(n), require(n), enabled(n), enable(n), disable(n), toggle(n) |
client.settings | find(module, setting) и конструкторы настроек: checkbox, slider, mode, select, button, range, color |
client.messages | info(), msg(), warn(), error(), overlay() |
client.ui | cursor(), menu_opened(), border(), border4() |
Аккаунт игрока в клиенте. Это свойства, а не методы: скобки не нужны. Значения живые, профиль приезжает с сайта уже после запуска клиента (profile.loaded), поэтому читай их там, где они нужны, а не запоминай при загрузке скрипта. Примеры и подробности лежат на отдельной странице Аккаунт игрока.
| Член | Описание |
|---|---|
profile.username / profile.name | Ник аккаунта на сайте, пустая строка до ответа |
profile.uid | Номер аккаунта |
profile.role | default, user, beta, media, support, moderator, alpha, admin, owner |
profile.staff / profile.admin | Персонал клиента; admin только у админа и владельца |
profile.loaded | Ответ сайта уже пришёл |
profile.subscription | Срок подписки строкой, как показывает клиент |
profile.subscription_end | Конец подписки в секундах эпохи или None |
profile.subscription_left | Сколько осталось в секундах или None |
profile.days_left | Дней до конца, inf у бессрочной, None если неизвестно |
profile.forever / profile.expired | Бессрочная подписка; срок уже вышел |
profile.avatar | Аватарка картинкой, её принимают d.image и ui.image |
profile.avatar_url | Ссылка на аватарку |
profile.avatar_of(name) | Аватарка другого пользователя клиента по нику |
profile.has_role(*names) | Совпала ли роль хотя бы с одним из имён |
profile.client / profile.version | Имя и версия клиента |
profile.all() | Всё сразу обычным словарём Python |
Меню клиента: какое открыто, где стоят его панели и на каком месте анимация. Свойства, скобки не нужны, значения живые. Рисовать вокруг меню дают события menu_render (слой под панелями) и post_menu_render (слой поверх): оба идут внутри анимации открытия, в тех же координатах, что и панели.
@events.menu_render
def draw(event):
ctx = event.getContext()
for panel in menu.panels:
ctx.drawShadow(panel.x - 8, panel.y - 8,
panel.width + 16, panel.height + 16,
30, border(18), Color(120, 190, 255).withAlpha(110 * menu.progress))| Член | Описание |
|---|---|
menu.opened | Меню на экране или доигрывает закрытие |
menu.type | panel, modern или None |
menu.progress | Открытость от 0 до 1: 1 меню на месте, 0 его нет |
menu.open | Анимация открытия с её кривой: на отскоке уходит за единицу |
menu.close | Закрытие от 0 до 1; идёт и без экрана, пока меню улетает в мир |
menu.closing | Меню закрывается |
menu.alpha | Насколько меню спрятано клавишей скрытия: 1 видно, 0 спрятано |
menu.scale | Масштаб этого кадра: 0.7 в начале открытия, 1 в конце |
menu.x, menu.y, menu.width, menu.height | Габарит меню: окно у modern, общая рамка всех панелей у panel |
menu.panels | Список панелей: у panel по одной на категорию, у modern одна, само окно |
menu.panel(name) | Панель по имени: combat, movement, visuals, player, other или window |
menu.all() | Всё сразу обычным словарём Python |
Панель это словарь, и читается он и точкой, и скобками: panel.x это то же самое, что panel["x"]. Так же устроены все словари, которые отдаёт клиент: элемент HUD, трек музыки, запись FunTime.
Ключи панели: name, x, y, width, height, а заодно посчитанные right, bottom, center_x, center_y.
HUD-элемент рисуется двумя способами: render (рисуешь сам) или layout (дерево виджетов, смотри секцию ui). Координаты в контексте рисования отсчитываются от элемента.
el = Hud("MyHud", width=100, height=20, x=8, y=8)
@el.render
def draw(d):
d.rect(0, 0, d.width, d.height, Color(0, 0, 0, 180))
d.text("Привет", 4, 4, size=7, color=Color(255, 255, 255))| Метод | Описание |
|---|---|
Hud(name, icon="hud/player", width=80, height=20, x=8, y=8, showing=True, render=None, visible_when=None, layout=None) | Создать элемент и вернуть его |
hud.find(name) | Найти элемент по имени |
hud.remove(name | element) | Удалить элемент |
hud.all() | Все скриптовые элементы HUD |
hud.mine() | Элементы, созданные этим скриптом |
hud.elements | Все элементы HUD клиента словарями: и встроенные, и скриптовые, с координатами и анимациями |
hud.info(name) | Один элемент по имени: ключ, его последний сегмент или перевод |
hud.show(name | element) | Включить элемент клиента. False, если имя незнакомое |
hud.hide(name | element) | Выключить элемент клиента |
hud.toggle(name | element) | Переключить и вернуть новое состояние: True, False или None |
hud.move(name | element, x, y) | Поставить элемент в точку: координаты те же, что в hud.info |
hud.elements нужен, чтобы рисовать вокруг чужих элементов: слой под ними даёт событие hud_render, слой поверх — post_hud_render. Числа те же, которыми HUD рисует себя.
| Ключ | Что внутри |
|---|---|
name / title / icon | Ключ имени, переведённое имя и значок элемента |
x, y, width, height | Где стоит и какого размера |
right, bottom, center_x, center_y | Посчитанные края и центр |
alpha | Прозрачность появления: 0 спрятан, 1 на месте |
appear / visible | Две половины этой анимации по отдельности |
scale | Масштаб кадра: элемент появляется не только прозрачностью |
select | Анимация выделения в режиме правки HUD |
drag / dragging | Анимация перетаскивания и признак, что элемент тащат прямо сейчас |
showing | Элемент включён игроком |
script | True у элементов, созданных скриптами |
Элемент HUD:
| Член | Описание |
|---|---|
x, y, width, height, showing | Свойства на чтение и запись |
name, icon, raw | Свойства только на чтение |
alpha, scale, drag, dragging, selecting | Анимации элемента: появление, масштаб кадра, перетаскивание, выделение в режиме правки |
pos(x, y) / size(w, h) | Переместить или изменить размер |
show() / hide() / remove() | Показать, скрыть, удалить |
render(fn) | fn(d) или fn(d, element): своя отрисовка |
layout(fn) | fn(ui): дерево виджетов |
signature(fn) | Строка-сигнатура: изменилась, layout пересобирается |
visible_when(fn) / show_when(fn) | Условие видимости |
el.checkbox / slider / mode / select / button / range / color | Настройки прямо на элементе, например el.slider("Size") |
Контекст рисования d (координаты от элемента, все методы возвращают d, так что можно цепочкой):
| Член | Описание |
|---|---|
d.x, d.y, d.width/d.w, d.height/d.h, d.alpha, d.drag, d.mouse_x, d.mouse_y, d.delta | Свойства контекста |
d.font(weight="medium", size=8) | Получить шрифт |
d.size(w, h) | Изменить размер элемента |
d.rect(x, y, w, h, color) | Прямоугольник (w и h по умолчанию равны размеру элемента) |
d.rounded_rect(x, y, w, h, radius=6, color) | Скруглённый прямоугольник |
d.border(x, y, w, h, radius=6, thickness=1, color) | Обводка |
d.shadow(x, y, w, h, radius=6, softness=12, color) | Тень |
d.client_rect(x, y, w, h, alpha, drag, squircle=3, radius, outline=False) | Фон в стиле клиента |
d.text(value, x, y, size=7, weight="medium", color, font, outline, outline_width=1) | Текст. outline это цвет обводки вокруг букв, outline_width её ширина в пикселях |
d.centered_text(...) / d.right_text(...) | Текст по центру или по правому краю, с теми же аргументами |
d.icon(name, x, y, size=8, color) | Иконка клиента |
d.item(stack, x, y, size=1) | Предмет |
d.effect(effect, x, y, size=10, color) | Иконка эффекта: объект или название |
d.image(texture, x, y, w, h, radius=0, color) | Картинка: ассет, обложка трека, аватарка (то же самое: d.texture) |
d.raw() | Полный набор методов рисования, тех же, что в render_2d |
Dynamic Island это статус-элемент сверху экрана.
st = IslandStatus("MyStatus", width=48, height=15, radius=7, expandable=False)
st.selected(True) # новый статус создаётся выключенным
@st.render
def draw(d):
d.centered_text("Hi", d.w / 2, 4)
st.visible_when(lambda: world.ingame())
st.click(lambda mx, my, btn: client.msg("клик"))
st.color(lambda: Color(255, 0, 0))
st.measure(lambda: st.size(60, 15))| Член | Описание |
|---|---|
IslandStatus(name, width=48, height=15, radius=7, expandable=False, render=, visible_when=, measure=, click=, color=) | Создать статус. Глобальный конструктор, как Module(...) |
island.find / remove / all / mine | Менеджер: поиск, удаление, списки статусов |
x, y, width/w, height/h, alpha, extended, expanding, name, raw | Свойства статуса |
size(w, h[, radius]) / radius(r) | Размер и скругление |
expandable(b) / selected(b) | Раскрываемость и включённость |
render(fn) / measure(fn) | Отрисовка и пересчёт размера |
click(fn) | fn(mouse_x, mouse_y, button) |
color(fn | Color) | Цвет статуса |
visible_when(fn) / remove() | Условие видимости, удаление |
Музыка, которая играет на компьютере: тот же источник, что и у Dynamic Island. Нет сессии, и всё возвращает None или нули.
track = music.current() # None если ничего не играет
if track:
client.msg(track["artist"] + " : " + track["title"])
line = music.current_lyric() # строка с таймкодами или None
if line:
client.msg("%d: %s" % (line["index"], line["text"]))| Метод | Описание |
|---|---|
music.active() / music.playing() | Есть ли сессия и играет ли она сейчас |
music.current() | Словарь: title, artist, owner, playing, position, position_ms, duration, duration_ms, progress, bpm, color, artwork, lyrics_synced, has_lyrics |
music.position() / position_ms() | Сколько отыграно, секунды и миллисекунды |
music.duration() / duration_ms() | Длина трека |
music.progress() | Доля от 0 до 1 |
music.bpm() | Темп трека или 0 |
music.color() / music.artwork() | Цвет и картинка обложки или None |
music.lyrics_synced() | Есть ли текст с таймкодами |
music.lyrics() | Весь текст: список из text, time_ms, cues |
music.current_lyric() / music.lyric_at(time_ms) | Строка сейчас или на заданное время; плюс index, progress, singing_progress, active |
music.play() / pause() / toggle() / next() / previous() / stop() | Управление плеером, True если команда ушла |
Свои звуковые файлы: wav, mp3 и ogg из папки скрипта, с диска или по ссылке. Звуки скрипта глохнут вместе с ним. Подробно - на странице Свои звуки.
sound.play("beep.wav") # один голос на файл, повтор начинает заново
sound.once("hit.wav", volume=0.5) # отдельный голос: звуки накладываются
track = sound.loop("ambient.mp3", volume=0.2) # играет по кругу
track.volume(0.1)
track.stop()| Метод | Описание |
|---|---|
sound.play(path, volume, speed, loop, category, overlap, on_end) | Проиграть с начала; один голос на файл |
sound.once(path, ...) | Отдельный голос, снимается сам после конца |
sound.loop(path, ...) / sound.load(path, ...) | По кругу; подготовить, не запуская |
sound.stop(path) / stop() / stop_all() | Остановить один файл или все звуки скрипта |
sound.playing() | Сколько звуков скрипта звучит сейчас |
звук: play() / stop() / pause() / resume() / toggle() | Управление голосом |
звук: volume(v) / speed(v) / loop(True) / category(name) | Без аргумента - чтение значения |
звук: on_end(fn) | Колбэк на естественный конец |
звук: playing / paused / position / duration / path | Свойства, читаются как поля |
Дерево виджетов используется в экранах (@screen) и в layout-режиме HUD-элементов. Контейнеры открываются через with.
@screen("Моё меню", 400, 300)
def menu(ui):
with ui.column(gap=8, pad=12, bg=Color(20, 20, 24), fill=True):
ui.text("Заголовок", size=10, weight="bold", color=Color(255, 255, 255))
with ui.row(gap=6, align="center"):
ui.button("Кнопка", on_click=lambda: client.msg("клик"))
ui.toggle("Флаг", lambda: flag.get(), lambda v: flag.set(v))
m = Module("Menu", "Other")
Button(m, "Открыть").action(lambda: menu.open())У экрана есть menu.open(), menu.close() и свойство menu.opened. Контейнеры это ui.column(**style) и ui.row(**style).
| Виджет | Сигнатура |
|---|---|
ui.text | (value_or_callable, size=0, weight="medium", color=None, **style), функция даёт реактивный текст |
ui.button | (label, **style), клик через on_click= |
ui.toggle | (label, get, set, **style) |
ui.switch | (get, set, **style) |
ui.slider | (label, lo, hi, value=0.0, on_change=None, step=0.0, **style) |
ui.slider_bar | (get, set, lo, hi, step=0.0, **style) |
ui.toggle_c | (get, on_click, on=None, off=None, knob=None, **style), перекрашиваемый |
ui.slider_c | (get, set, lo, hi, step=0, track=, fill=, ring=, inner=, thumb_radius=, thumb_border=, track_height=, **style) |
ui.text_input | (get, set, placeholder="", bg=None, color=None, size=0, weight="regular", **style) |
ui.swatch | (get, **style), кружок цвета |
ui.setting | (py_setting, **style), настройку рисует сам клиент |
ui.icon | (name, size=10, color=None, **style) |
ui.image | (texture, size=10, color=None, radius=0, **style) |
ui.effect | (effect, size=12, color=None, **style), функция вместо эффекта даёт реактивную иконку |
ui.space | (px=4) |
ui.divider | (**style) |
ui.color | (name), цвет темы: accent, text, background/bg, second, outline, white |
Стили это именованные аргументы любого узла:
| Группа | Ключи |
|---|---|
| Размеры | width, height, size=(w, h), min_size, max_size, gap, pad/padding (число или (v, h)) |
| Форма | radius, radius_bottom, squircle, border=(width, color), color/bg (ColorRGBA или функция), blur (число или (число, ColorRGBA)), glass (True или число) |
| Раскладка | fill, fill_width, fill_height, align (start|center|end|stretch), justify (start|center|end|between|around|evenly), direction (up|down|left|right), columns, wrap, center, stack, sticky, collapse |
| Скролл | scroll, scrollbar (auto|always|never) |
| Взаимодействие | interactive, on_click, on_click_pos, cursor (hand|text|crosshair|…), draggable (True или x|y|none|all), visible_when |
| Анимация | enter/exit (none|fade|vanish|fade_slide|up|down|left|right|pop|fade_pop), enter_slide, exit_slide, motion (fast|smooth|signal|spring|spring_snap|soft), stagger, fade |
Экран без раскладки: рисуешь сам, координаты абсолютные, размер экрана лежит в d.width и d.height. Доступны те же методы, что в контексте HUD: rect, rounded_rect, border, client_rect, text, centered_text, right_text, icon, image, effect, font, raw.
@raw_screen("Raw", 400, 300)
def render(d):
d.rect(10, 10, 100, 20, Color(255, 255, 255))
d.text("Hi", 12, 12)
@render.on_click
def click(mx, my, btn): ...
render.open()В событиях render_2d и pre_render_2d холст для рисования берут через event.getContext().
@events.render_2d
def draw(event):
ctx = event.getContext()
ctx.drawRect(10, 10, 100, 20, Color(255, 255, 255))
ctx.drawRoundedRect(10, 40, 100, 20, border(6), Color(0, 0, 0, 180))
ctx.drawText(font("medium", 8), "Привет", 12, 44, Color(255, 255, 255))| Метод | Сигнатура |
|---|---|
drawRect | (x, y, w, h, color) |
drawRoundedRect | (x, y, w, h, border, color) |
drawRoundedBorder | (x, y, w, h, thickness, border, color) |
drawSquircle | (x, y, w, h, squirt, border, color) |
drawSquircleBorder | (x, y, w, h, thickness, squirt, border, color) |
drawShadow | (x, y, w, h, softness, border, color) |
drawBlurredRect | (x, y, w, h, blurRadius, border, color) или (x, y, w, h, blur, squirt, border, color) |
drawLiquidGlass | (x, y, w, h, squirt, power, border, color) |
drawClientRect | (x, y, w, h, alpha, dragAnim, squircle[, radius[, outline]]) |
drawLoadingRect | (x, y, w, h, progress, border, color) |
drawText | (font, text, x, y, color) |
drawCenteredText | (font, text, x, y, color) |
drawRightText | (font, text, x, y, color) |
drawTextWithShadow | (font, text, x, y, color, shadowColor, offX, offY, blur) |
drawTextWithOutline | (font, text, x, y, color, outlineColor, thickness[, steps]): есть и drawCenteredTextWithOutline, drawRightTextWithOutline |
drawFadeoutText | (font, text, x, y, color, fadeStart, fadeEnd[, maxWidth]) |
drawIcon | (name, x, y, size[, color]) |
drawItem | (itemStack, x, y, size) |
drawEffect | (effect, x, y, size[, color]): эффект объектом или названием |
drawHead | (entity, x, y, size, border, color) |
drawTexture | (identifier, x, y, w, h[, color]) |
drawRoundedTexture | (identifier, x, y, w, h, border[, color]) |
drawEntity | (x1, y1, x2, y2, size, f, mouseX, mouseY, entity) |
drawArc | (x, y, size, thickness, startAngle, endAngle, color) |
drawCircleProgress | (cx, cy, radius, thickness, progress, color) |
drawLine | (from, to, color): точки создаёт jimport("net.minecraft.util.math.Vec2f") |
pushMatrix() / popMatrix() | (без аргументов) |
Все методы, которые рисуют, первым аргументом принимают событие render_3d. По умолчанию нарисованное видно сквозь блоки: render3d.depth(True) включает режим, в котором всё дальше прячется за стенами, а through у одного вызова важнее режима.
@events.render_3d
def draw(event):
for p in world.players():
render3d.box(event, p, Color(255, 0, 0))| Метод | Сигнатура |
|---|---|
render3d.depth | (on=True): дальше всё прячется за блоками; годится и как with render3d.depth() |
render3d.depth_enabled | (): стоит ли сейчас этот режим |
render3d.through_walls | (on=True): наоборот, рисовать сквозь блоки |
render3d.line | (event, start, end=None, color=None, through=None): точки [x, y, z] или 6 чисел |
render3d.marker | (event, pos, size=0.18, color=None, through=None): pos это точка [x, y, z] |
render3d.box | (event, target, color=None, through=None): target это сущность или коробка |
render3d.filled_box | (event, target, color=None, through=None) |
render3d.glowing_box | (event, target, color=None, through=None) |
render3d.box_gradient | (event, target, bottom_color, top_color, through=None) |
render3d.filled_box_gradient | (event, target, bottom, top, through=None) |
render3d.box_at | (event, x, y, z, width, height, depth, color=None, through=None) |
render3d.filled_box_at | (event, x, y, z, w, h, d, color=None, through=None) |
render3d.ring | (event, target, radius=0.8, y_offset=0.05, segments=48, color=None, through=None) |
render3d.target | (event, target=None, color=None, through=None): композит; target=None берёт цель Aura |
render3d.billboard | (event, texture, pos, width=1.0, height=None, color=None, roll=0.0, additive=False, through=None) |
render3d.effect | (event, effect, pos, size=0.5, color=None, roll=0.0, additive=False, through=None): иконка эффекта билбордом |
render3d.billboards | (event, texture, particles, additive=True, through=None): пачка одним вызовом, по 8 чисел на частицу (x, y, z, размер, r, g, b, a) |
render3d.lines | (event, segments, additive=True, through=None): пачка одним вызовом, по 10 чисел на отрезок (x1, y1, z1, x2, y2, z2, r, g, b, a) |
render3d.text | (event, text, pos, size=0.25, color=None, font=None, outline=None, outline_width=0.06, outline_steps=4, shadow=None, shadow_offset=None, facing=True, yaw=0.0, pitch=0.0, roll=0.0, align="center", through=None, additive=False): size это высота буквы в блоках |
render3d.texts | (event, items, ...): пачка надписей одним вызовом; элемент это словарь или кортеж (текст, точка, размер, цвет, наклон, yaw, pitch) и может нести свои углы |
render3d.text_width | (text, size=0.25, font=None): ширина в блоках |
render3d.text_height | (size=0.25, font=None): шаг между строками в блоках |
render3d.letters | (text, size=0.25, font=None): список (символ, смещение слева, ширина) в блоках |
Свой шейдер GLSL. Shader(...) зовут один раз в теле скрипта, подробности на странице Свои шейдеры.
glow = Shader("glow", """
uniform float Power;
void main() {
fragColor = vec4(Color.rgb, Color.a * exp(-distance(FragCoord, vec2(0.5)) * Power));
}
""")
@events.render_2d
def draw(event):
glow.set("Power", 6.0)
glow.color(Color(120, 200, 255))
glow.rect(event.getContext(), 40, 40, 160, 80)| Метод | Сигнатура |
|---|---|
Shader | (name, fragment, vertex=None): собрать шейдер из текста |
shader.load | (name, fragment, vertex=None): то же, но текст из файла рядом со скриптом |
shd.set | (name, a[, b, c, d]): float, vec2, vec3 или vec4 |
shd.set_int | (name, value): int |
shd.color | (color, name="Color"): цвет в vec4 |
shd.texture | (unit, image): картинка в Sampler0..Sampler3, unit от 0 до 7 |
shd.matrix | (name, matrix): матрица 4 на 4 |
shd.rect | (ctx, x, y, width, height): прямоугольник на экране |
shd.fullscreen | (event): эффект по всему кадру мира, из render_3d |
shd.quad3d | (event, pos, width, height=None, mode="billboard", additive=False, depth=False): квад в мире; mode это billboard, ground или wall, depth=True прячет его за геометрией |
shd.mesh3d | (event, vertices, origin=(0,0,0), mode="triangles", colors=False, additive=False, depth=True, cull=False): своя геометрия в мире, по 5 чисел на вершину (x, y, z, u, v) или 9 с цветом 0..255 |
shd.mesh2d | (ctx, vertices, mode="triangles", colors=False): своя геометрия на экране, по 4 числа на вершину (x, y, u, v) или 8 с цветом |
shd.dispose | (): снять шейдер; вместе со скриптом снимается сам |
Встроенные переменные шейдера: FragCoord, Size, Time, Color, Resolution, MousePos, GuiScale, Sampler0..Sampler3, а для эффектов по миру ещё CamPos и InvViewProj. Объявлять их не надо.
| Метод | Описание |
|---|---|
world.ingame() | bool: мир и игрок существуют |
world.self() | Свой игрок, то же что mc.player |
world.entities() | Все сущности |
world.living() | Только LivingEntity |
world.players() | Другие игроки, без себя |
world.nearest_player() | Ближайший игрок или None |
world.target() | Текущая цель Aura |
world.time() | Время мира |
Прямой доступ к Minecraft идёт через mc:
mc.player, mc.world, mc.options
mc.getSession().getUsername()
mc.getCurrentFps()
p = mc.player
p.getX(), p.getY(), p.getZ()
p.getYaw(), p.setYaw(v)
p.getHealth(), p.isOnGround()
p.getNameForScoreboard() # ник строкой; getName() отдаёт Text
p.getId() # номер сущности в сети
# клавиши: forwardKey, backKey, leftKey, rightKey,
# jumpKey, sneakKey, sprintKey, attackKey, useKey
mc.options.forwardKey.setPressed(True)Импорт классов игры: имена пишутся полностью, так же как в самой игре.
from net.minecraft.entity import LivingEntity
Box = jimport("net.minecraft.util.math.Box")Свои команды чата: подробности на странице Свои команды. Аргументы берутся из сигнатуры функции, описание из строки под ней.
@command("hello", desc="Здоровается", aliases=["hi"])
def hello(ctx):
ctx.msg("Привет!")
@command("tp")
def tp(ctx, x: int, y: int, z: int):
"""Телепорт по координатам"""
newton.goto(x, y, z, radius=1)
@tp.sub("home")
def tp_home(ctx):
"""Домой"""
newton.goto(120, 64, -340, radius=1)| Член | Описание |
|---|---|
command(name, desc="", aliases=None, suggests=None) | Декоратор команды, возвращает объект команды |
cmd.sub(name, desc=, aliases=, suggests=) | Декоратор подкоманды |
cmd.remove() / cmd.name | Снять команду, её имя |
commands.add(name, fn, desc=, aliases=, suggests=) | То же, что декоратор, но без него |
commands.remove(name | cmd) | Снять свою команду. Чужие не трогает |
commands.exists(name) / commands.all() | Занято ли имя, список всех команд клиента |
commands.run(line) / commands.prefix() | Выполнить команду, текущий префикс |
ctx.msg / warn / error / overlay(text) | Ответ игроку |
ctx.name / ctx.args / ctx.get(i, default) | Имя команды и аргументы |
Типы аргументов: int, float, bool, str и строковые "player", "module", "block" с готовыми подсказками. Значение по умолчанию делает аргумент необязательным, *words собирает остаток строки.
Newton ведёт персонажа сам: ходьба к точке, полёт на элитре, копка блоков и работа с областью. Подробности на странице Ходьба и маршруты.
newton.goto(100, 64, -200, radius=1) # точка: три числа, список или сущность
newton.fly_to(1500, 120, -800) # на элитре
newton.mine("diamond_ore") # копать ближайшие такие блоки
newton.excavate([100, 60, 200], [110, 66, 210])
newton.fill([100, 60, 200], [110, 66, 210], "stone")
newton.cancel()| Метод | Описание |
|---|---|
newton.ready() / active() | Newton запущен / сейчас что-то выполняет |
newton.goto(точка, radius=0, elytra=False) | Идти к блоку |
newton.goto_near(точка, radius=1) | Идти в радиус от блока |
newton.goto_xz(x, z) / goto_y(y) | Прийти в колонку X,Z / на высоту |
newton.fly_to(точка, keep_y=True) | Лететь на элитре |
newton.mine(block) | Копать ближайшие блоки этого типа |
newton.excavate(c1, c2, block=None) | Раскопать область, можно только один тип блока |
newton.fill(c1, c2, block) | Заполнить область блоком |
newton.select(точка) / selection() / clear_selection() | Выделение области, то же что .newton sel |
newton.excavate_selection(block=None) / fill_selection(block) | То же самое по текущему выделению |
newton.cancel() / pause() / resume() / paused() | Управление текущей задачей |
newton.process() / status() | Имя задачи и строка состояния |
newton.path() / progress() | Маршрут: step, steps, next, goal / доля от 0.0 до 1.0 |
newton.command("goto 100 64 -200") | Команда Newton строкой, без точки и слова newton |
newton.safewalk / newton.logging | Свойства: не падать с краёв, писать отчёт в чат |
Ход работы приходит событиями newton_started, newton_path, newton_node, newton_finished, newton_failed.
Уведомления клиента: плашки поверх игры. Подробности на странице Уведомления.
notify.island("Готово", "success") # строка в Dynamic Island
notify.crosshair("Внимание", "Рядом игрок") # плашка под прицелом
notify.item("Нашёл", "diamond", highlight="алмаз")| Метод | Описание |
|---|---|
notify.island(text, type="info") | Строка в Dynamic Island. type: info, success, error |
notify.success / error / info (text) | То же с готовым цветом |
notify.crosshair(title, desc, type="info") | Плашка под прицелом |
notify.item(text, item, highlight=None, color=None) | Плашка с иконкой предмета |
notify.effect(text, effect, highlight=None, color=None) | Плашка с иконкой эффекта |
notify.sound() / notify.count() | Звук уведомления, сколько плашек на экране |
Каждая показанная плашка приходит событием notification: getStyle(), getType(), getTitle(), getText().
Инвентарь: слоты нумеруются как в игре (0-8 хотбар, 9-35 рюкзак, 36-39 броня, 40 левая рука). Часть инвентаря задаётся словом: hotbar, main, armor, offhand, all.
slot = inventory.find("totem_of_undying", "hotbar")
if slot is not None:
inventory.to_offhand(slot)
inventory.select(2)
inventory.total("ender_pearl")
inventory.items("hotbar") # [(слот, id, количество), ...]| Метод | Описание |
|---|---|
inventory.selected() / select(slot) | Что в руке, взять слот в руку |
inventory.id / label / count / stack (slot) | Что лежит в слоте |
inventory.find(item, where) / find_all / has / total | Поиск и счётчики |
inventory.empty(where) / items(where) / slots(where) | Свободный слот, содержимое, номера |
inventory.hold(item) | Взять предмет в руку, если он в хотбаре |
inventory.swap / move / quick_move / to_offhand / to_armor | Перекладывание предметов |
inventory.with_slot(slot, fn) | Действие с временной сменой слота |
inventory.durability(slot) / enchant(slot, name) | Прочность в процентах, уровень зачарования |
inventory.offhand_is(item) / container_open() | Что в левой руке, открыт ли контейнер |
Баффы и дебаффы игрока: список, время, иконки. Тот же объект доступен как buffs. Эффект всюду можно назвать строкой (speed или minecraft:speed). Подробности на странице Эффекты.
for eff in effects.list():
client.msg("%s %s" % (eff.label, eff.time))
if effects.has("speed"):
lvl = effects.level("speed")
ctx.effect("strength", 0, 0, 12) # иконка эффекта в контексте рисования| Метод | Описание |
|---|---|
effects.list(hidden=False) | Эффекты игрока, отсортированы по названию |
effects.good(hidden=False) / bad(hidden=False) | Только полезные или только вредные |
effects.of(entity, hidden=False) | Эффекты существа: клиент знает лишь присланные сервером |
effects.get(effect, entity=None) | Эффект или None |
effects.has(effect) | Висит ли прямо сейчас |
effects.level / amplifier через объект | effects.level(effect): уровень с единицы, 0 если нет |
effects.duration(effect) / seconds(effect) | Сколько осталось: тики и секунды, у бесконечного -1 |
effects.time(effect) | Оставшееся время строкой 01:23 |
effects.info(effect) | Описание типа, даже если эффекта нет на игроке |
effects.types() | Все названия эффектов, какие знает игра |
effects.draw(ctx, effect, x, y, size=10, color=None) | То же, что ctx.effect(...) |
len(effects) / "speed" in effects / for eff in effects | Объект работает и как список |
Свойства одного эффекта (свойства, а не методы — скобки не нужны):
| Свойство | Описание |
|---|---|
id, key, name, label | minecraft:speed, speed, Скорость, Скорость II |
level, amplifier | Уровень с единицы и с нуля |
duration, seconds, time | Сколько осталось: тики, секунды, строка 01:23 |
color, category, good, bad | Цвет частиц, good/bad/neutral и две проверки |
infinite, ambient, particles, visible, hidden, active | Признаки эффекта |
atlas, uv, instance, raw | Для тех, кто рисует сам или лезет в игру напрямую |
draw(ctx, x, y, size=10, color=None) | Нарисовать иконку |
Цвета текущей темы клиента. Работают везде, не только в лейауте.
ctx.rect(0, 20, 120, 2, theme.accent())
ctx.text("текст", 8, 6, size=7, color=theme.text())
ctx.text("на акценте", 8, 20, size=7, color=theme.readable(theme.accent()))| Метод | Описание |
|---|---|
theme.color(name) | accent, text, background, second, outline, shadow, on_accent, flat, separator |
theme.accent() / text() / background() / second() / outline() / on_accent() | Те же цвета отдельными методами |
theme.readable(color) | Читаемый текст для своей заливки |
theme.name() / theme.dark() | Имя темы, признак тёмной |
theme.set_accent(color) | Сменить акцент клиента |
Скин, плащ и элитра так, как их видит твой клиент. Настоящий скин лежит на серверах Mojang, поэтому подмена видна только тебе, а правила снимаются вместе со скриптом. Подробности на странице Скины и плащи.
skins.me(skin="Notch", cape="optifine:Notch")
skins.skin("Player123", "skins/my.png")
skins.model("Player123", "slim")
skins.all(skin="Herobrine")
skins.reset("Player123")| Метод | Описание |
|---|---|
skins.set(target, skin, cape, elytra, model) | Всё сразу именованными аргументами |
skins.me(...) / skins.all(...) | То же самое для себя и для всех игроков |
skins.skin(target, source) | Скин: ник, файл, ссылка, текстура или None |
skins.cape(target, source) | Плащ, ещё понимает "optifine:ник" |
skins.elytra(target, source) | Текстура элитры |
skins.model(target, name) | Толщина рук: slim или wide |
skins.hide_cape(target) | Убрать плащ совсем |
skins.reset(target) / skins.clear() | Снять правило цели или все правила скрипта |
skins.targets() / skins.get(target) | Список целей и что у цели подменено |
Свой элемент ESP рядом со встроенными: галочки по целям (игроки, мобы, животные, предметы и виды игроков) рисует клиент, скрипт получает готовую цель. Подробности на странице Свои элементы ESP.
el = Esp("esp.mybox", targets=["players", "mobs"], enable=["others"])
color = ColorSetting(el, "esp.mybox.color")
@el.filter
def only_close(entity):
return entity.distanceTo(mc.player) < 20
@el.render
def draw(entity, event):
render3d.box(event, entity, color.get())| Вызов | Описание |
|---|---|
Esp(name, targets, enable) | Новый элемент; имя это ключ локализации |
@el.render / @el.render_all | Рисование цели или всех целей кадра разом |
@el.filter | Своя проверка поверх галочек меню |
el.enable_for(...) / el.enabled() / el.remove() | Что включено сразу, рисует ли сейчас, убрать |
esp.enabled() / esp.elements() | Включён ли модуль ESP, имена всех элементов |
esp.to_screen(x, y, z) | Точка мира в координатах экрана или None |
Переводы скрипта. Вместо готовой строки пишут ключ, а клиент подставляет язык игрока: имена настроек, значения режимов и описания модулей он переводит сам. Подробности на странице Локализация.
lang.load({
"ru_ru": {"mymod.speed": "Скорость", "mymod.hi": "Привет, %s"},
"en_us": {"mymod.speed": "Speed", "mymod.hi": "Hi, %s"},
})
speed = Slider(mod, "mymod.speed") # надпись в меню на языке игрока
client.msg(lang("mymod.hi", "Steve"))
lang.plural(5, "игрок", "игрока", "игроков")| Метод | Описание |
|---|---|
lang(key) / lang(key, value, ...) | Перевод ключа, при желании с подстановками %s, %d |
lang.load({lang: {...}}) / lang.add(lang, {...}) | Объявить переводы |
lang.load_file(path) | Переводы из json-файла или по ссылке |
lang.current() | Язык клиента: ru_ru, en_us, uk_ua, pl_pl |
lang.has(key) | Есть ли перевод: свой или клиентский |
lang.plural(n, ...) | Форма слова по числу |
lang.clear() | Снять переводы этого скрипта |
Коды клавиш и их состояние. Нужен рядом с событиями key и mouse: сравнивать код надёжнее, чем подпись клавиши, потому что подпись зависит от языка клиента.
@events.key
def on_key(event):
if event.isPress() and event.getKey() == keys.G:
client.msg("нажата G")
if keys.down("LEFT_SHIFT") and keys.mouse(1):
client.msg("шифт и правая кнопка")| Метод | Описание |
|---|---|
keys.G / keys.LEFT_SHIFT / keys.F5 | Код клавиши по имени, прямо через точку |
keys.code(name) | То же самое, но имя можно собрать в переменной. Понимает и сочетание: "CTRL+G". Нет такой клавиши, вернёт -1 |
keys.name(code) | Подпись клавиши так, как её показывает клиент |
keys.down(key) | Зажата ли клавиша прямо сейчас. Принимает и код, и имя |
keys.mouse(button) | Зажата ли кнопка мыши: 0 левая, 1 правая, 2 колесо |
keys.x() / keys.y() / keys.cursor() | Где курсор, в единицах render_2d |
keys.names() | Все имена клавиш, которые понимает code() |
Имена клавиш это имена GLFW: A, SPACE, LEFT_SHIFT, F5, а кнопки мыши это LMB, RMB, MMB, MOUSE4. Те же имена понимает команда .bind. Сочетание пишут через плюс: CTRL+G, ALT+SHIFT+F.
Выбор цели правилами боевых модулей клиента: тот же фильтр и та же сортировка.
victim = target.best(players=True, range=6, sort="distance")
everyone = target.all(players=True, mobs=True, range=16)
current = target.current() # кого бьёт Aura| Метод | Описание |
|---|---|
target.best(**настройки) | Лучшая цель или None |
target.all(**настройки) | Все подходящие, по порядку сортировки |
target.valid(entity, **настройки) | Подходит ли эта сущность |
target.current() / target.living() | Текущая цель Aura |
target.add / remove / clear / list / is_target | Приоритетные ники, тот же список что у команды .target |
Настройки: players, mobs, animals, invisibles, naked, friends, users, armor_stands, exclude_teammates, range, sort (distance, health, fov, bad_armor, good_armor).
Данные FunTime: ивенты, шахты, данжи, игроки, баны. Подробности на странице Данные FunTime.
for event in funtime.events():
client.msg("%s: %s" % (event["name"], event["status"]))
funtime.fetch_players(lambda players: client.msg("онлайн: %d" % len(players)))| Метод | Описание |
|---|---|
funtime.ready() | Собраны ли данные. Запросы fetch работают и без этого |
funtime.events() / mines() | Ивенты и шахты из памяти клиента |
funtime.copper_dungeons() / warden_cities() | Данжи и города стража: сундуки и игроки |
funtime.system_info() | Сводка по количеству |
funtime.fetch_events / fetch_mines (fn, params=None) | Свежий ответ сервера строкой |
funtime.fetch_players / fetch_bans (fn, params=None) | Списки словарей |
funtime.solve_captcha(base64, fn) | Разбор капчи: solved, text, percent |
Свой режим ротации для Aura пишут классом или декоратором.
class MyRot:
name = "My Rot"
def rotate(self, ctx):
yaw, pitch = ctx.default() # углы на цель по умолчанию
return (yaw, pitch) # или {"yaw": ..., "pitch": ...}
def attack(self): ... # необязательно
def can_attack(self): return True # необязательно
def target_null(self): ... # необязательно
def update(self): ... # необязательно
aura.add(MyRot(), select=True)
@aura.rotation("Simple", select=True)
def rotate(ctx):
return ctx.to(ctx.target)| Член | Описание |
|---|---|
aura.add(mode, select=False) | Добавить объект-режим |
aura.add_rotation(name, rotate=, attack=, can_attack=, target_null=, update=, select=) | Добавить режим из функций |
aura.rotation(name) | Декоратор над функцией rotate |
aura.select(name) / remove(name | mode) / has(name) | Выбрать, снять, проверить |
aura.current() / aura.target() | Текущий режим и текущая цель |
aura.enabled / attack_distance / module | Свойства Aura |
ctx (в rotate) | Поля: handler, attack_distance, walls, ray_trace, move_correction, target, rotations |
ctx.default() / ctx.to(entity=None) / ctx.apply(yaw, pitch, **kw) | Методы контекста ротации |
Ротации вне Aura это объект rotations:
| Метод | Описание |
|---|---|
rotations.current() | Текущие углы обработчика |
rotations.player() | Углы игрока |
rotations.to(entity) | Углы на сущность |
rotations.to_point(x, y, z) | Углы на точку |
rotations.default(target) | Углы на цель, как их взяла бы Aura |
rotations.gcd(fy, fp, ty, tp) | Округление по GCD |
rotations.gcd_step(fy, fp, ty, tp, step[, pitch_step]) | GCD с шагом |
rotations.vanilla_step() | Ванильный шаг GCD |
rotations.idling() | Камеру сейчас никто не крутит |
rotations.apply(yaw, pitch, correction="silent", priority="normal", yaw_speed=180, pitch_speed=180, return_speed=180, vanilla_gcd=True, raw_gcd=False) | Применить углы |
c = Color(255, 0, 0) # r, g, b (0..255), alpha=255
c = Color(255, 0, 0, 128) # с альфой
c = Color.from_hex("#ff0000") # или "#ff0000aa"
c = Color.from_int(0xFFFF0000)
c = Color.from_hsb(0.5, 1.0, 1.0) # каждое 0..1
ColorRGBA.WHITE, ColorRGBA.BLACK, ColorRGBA.RED
ColorRGBA.GREEN, ColorRGBA.BLUE, ColorRGBA.YELLOW
c.withAlpha(120) # копия с другой альфой (0..255)
c.mulAlpha(0.5) # умножить альфу
c.mix(other, 0.5) # смешать два цвета
c.toHex() # "#rrggbbaa"Шрифт это font(weight, size). Веса: noto, bold, medium, regular, semibold, roundbold. Скругления это border(6) (все углы) и border4(10, 0, 10, 0) (tl, tr, br, bl).
f = font("medium", 8)
client.font_width("medium", 8, "text")
client.font_height("medium", 8)
tex = assets.image("assets/logo.png") # путь относительно папки scripts/
tex = assets.image("https://site.ru/logo.png") # или ссылка: качается один раз
assets.resource("icons/logo.png") # ресурс клиента (assets/rockstar/...)
assets.ttf("Inter", "assets/Inter.ttf", 9) # свой шрифт из ttf/otf, файлом или ссылкой
assets.svg("моё/сердце", "assets/heart.svg") # свой значок: дальше d.icon("моё/сердце")
assets.svg_text("моё/звезда", "<svg viewBox='0 0 24 24'>...</svg>")
assets.download("https://site.ru/data.json", on_ready) # любой другой файл по ссылке
assets.scripts_dir()
paths.root() # .minecraft/Rockstar, папка клиента (то же, что client.gameDir())
paths.scripts() # .minecraft/Rockstar/scripts
paths.runtime() # .minecraft/Rockstar/runtime, сам CPython лежит внутри, в python/db = Storage("myscript") # scripts/storage/myscript.json
db.set("kills", 10).save()
db.get("kills", 0)
db["kills"] = 5
db.all()
db.remove("kills")
db.clear()
db.load()
t = Timer()
if t.finished(500): # прошло 500 мс или больше
t.reset()
t.elapsed() # мс с последнего reset| Метод | Описание |
|---|---|
vec.add(a, b) / vec.sub(a, b) | Сложение и вычитание векторов |
vec.scale(a, s) | Умножение на число |
vec.dot(a, b) | Скалярное произведение |
vec.length(a) | Длина вектора |
vec.distance(a, b) | Расстояние между точками |
vec.normalize(a) | Нормализация |
vec.lerp(a, b, t) | Линейная интерполяция |
vec.clamp(v, lo, hi) | Ограничение одного числа |
Скрипт работает внутри процесса игры, поэтому доступ к памяти процесса и к запуску чужого кода закрыт: иначе скриптом снимали бы дамп клиента, а купленный на маркете скрипт мог бы делать что угодно на машине покупателя. Запрет срабатывает на месте: скрипт падает с текстом скриптам запрещено: ... (питон) или класс ... закрыт для скриптов (мост в JVM).
| Закрыто | Что именно |
|---|---|
| FFI | ctypes, _ctypes, cffi, _cffi_backend, pymem |
| Запуск процессов | subprocess.Popen, os.system, os.startfile, os.exec*, os.spawn*, os.kill и _winapi (CreateProcess, OpenProcess, TerminateProcess). Сами модули subprocess и multiprocessing импортируются как раньше, закрыт именно запуск |
| Сторонние нативки | .pyd и .dll грузятся только из встроенного рантайма — свой файл рядом со скриптом не подключить, и записать что-то в папку рантайма скрипт тоже не может. os.add_dll_directory принимает только пути внутри рантайма |
| torch | В игре не импортируется: он стоит в рантайме ради обучения нейро-ауры (оно идёт отдельным процессом), а torch.ops.load_library грузит в процесс игры любую dll. Для математики есть numpy, он работает |
| Реестр Windows | Запись: winreg.CreateKey, SetValue, DeleteKey, DeleteValue, SaveKey, LoadKey, ConnectRegistry. Чтение разрешено |
| Классы JVM | sun.*, jdk.*, com.sun.*, java.lang.reflect.*, java.lang.invoke.*, java.lang.foreign.*, java.security.*, javax.script.*, org.lwjgl.system.*, io.netty.util.internal.*, jep.*, а поимённо — Runtime, ProcessBuilder, Class, ClassLoader, Thread. У System закрыты только load, loadLibrary, exit, setSecurityManager: остальное (currentTimeMillis, nanoTime, getProperty, out) работает через jimport("java.lang.System"), но не через питоновский from java.lang import System |
| import java-пакетов | Работает как раньше для java.*, javax.*, org.joml, org.lwjgl, com.mojang, net.fabricmc (from java.util import ArrayList), но закрытые классы из таблицы не найдутся. Классы игры (net.minecraft.*) по-прежнему берут через jimport(...): только он знает обфусцированные имена |
Алиасы команды: .script, .python.
| Команда | Алиасы | Что делает |
|---|---|---|
.py list | нет | Список скриптов и их статус (строки кликабельны) |
.py load <имя> | use, enable, true | Включить скрипт |
.py unload <имя> | disable, off, false | Выключить скрипт |
.py toggle <имя> | нет | Переключить |
.py reload | update | Пересканировать папку и перезагрузить всё |
.py create <имя> | add | Создать новый файл-скрипт из заготовки. Если такой уже есть, команда откажется |
.py delete <имя> | remove, del | Удалить файл скрипта |
.py install <пакет> | pip, i | pip install во встроенный python-рантайм |
.py sync | push, upload | Отправить скрипты на сайт вручную. Обычно они уезжают туда сами, сразу после сохранения файла |
.py dir | direction | Открыть папку скриптов в проводнике |