> For the complete documentation index, see [llms.txt](https://docs.nursultan.fun/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.nursultan.fun/scripting-api-ru/eshyo/pesochnica-i-limity.md).

# Песочница и лимиты

Скрипты выполняются в песочнице. Это нужно, чтобы чужой скрипт не мог сделать с твоим компьютером ничего лишнего.

## Что доступно

* Всё API Nursultan — то, что описано в этой документации.
* Стандартная библиотека Kotlin: коллекции, строки, последовательности, математика, `Random`.
* Часть Java: коллекции, стримы, `java.time`, `java.math`, обёртки над числами.

Импорты писать не нужно — всё уже доступно на верхнем уровне.

## Чего нет

* Файлы и папки.
* Сеть.
* Потоки и таймеры Java.
* Рефлексия и загрузка классов.
* Прямой доступ к внутренностям Minecraft и клиента.

Скрипт, который пытается что-то из этого, **не загрузится**: клиент проверяет его перед запуском и пишет, какой символ запрещён.

Работать с файлами не нужно и незачем — для сохранения есть конфиги, для чтения мира есть API.

## Сколько можно думать

| Что                                 | Лимит  |
| ----------------------------------- | ------ |
| обработчик события, команда, кнопка | 250 мс |
| выполнение скрипта при загрузке     | 5 с    |

Превысил — скрипт останавливается с ошибкой, в которой написан файл и строка:

```
auto-jump.kts:14  script ran for more than 250 ms without giving the game back
```

Скрипт при этом выключается, а игра продолжает работать. Клиент не зависнет из-за чужого бесконечного цикла.

Отсюда простое правило: не пиши циклов, которые могут не закончиться, и не делай тяжёлую работу за один тик. Раздели её:

```kotlin
var index = 0

on<ClientTickEvent> {
    val all = world.entities()
    val end = minOf(index + 20, all.size)
    for (i in index until end) {
        // немного работы за тик
    }
    index = if (end >= all.size) 0 else end
}
```

## Ошибки

Всё, что упало внутри скрипта, попадает в консоль скриптов вместе с файлом и строкой. Игра из-за этого не падает.

Если обработчик падает **пять раз подряд**, скрипт выключается сам — чтобы не заваливать консоль одной и той же ошибкой. Один удачный вызов счётчик обнуляет.

## Что стоит помнить

* `world.entities()` каждый кадр — плохо. Раз в тик и в переменную — нормально.
* Лучи и предсказание — это расчёты, а не чтение полей. Считай столько, сколько правда нужно.
* Запись конфига на диск не бесплатна: `save()` не место в обработчике тика.
* Подсказки команд вызываются во время печати — держи их лёгкими.

## Совместимость

Скрипт, который не трогает пакеты, переживает обновление Minecraft без правок. Всё остальное API — независимо от версии игры.

Если скрипт требует чего-то нового, попроси версию API в начале файла:

```kotlin
requireApi(1)
```

На старом клиенте он не загрузится с понятной ошибкой вместо странного поведения.
