CraftTweaker 1.12.2 Основы

Назад

## Начало работы с CraftTweaker

CraftTweaker использует собственный язык программирования под названием ZenScript, ZenScript выполняет код из файлов с расширением .zs, которые хранятся в папке scripts.

ZenScript - это язык программирования который считывает код "сверху вниз", что означает, что импорт должен быть в верхней части файла, объявления переменных должны быть в верхней части файла, однако на это нет никаких ограничений, переменная может быть определена в любом месте скрипта, однако она не будет доступна для строки над объявлением переменной

###  **Ваш Первый Скрипт**

Думаю не для кого не секрет, что первому чему вас учат в программировании это простое "*hello world !*". Создайте файл *hello.zs* в папке *scripts*. И напишите в нем следующее.

```
print("Hello world!");

```

Теперь запустите Minecraft и откройте файл crafttweaker.log, в папке майнкрафт, либо напишите в чате /ct log

###  **Файл CraftTweaker.log**

Файл *crafttweaker.log* использует определенный синтаксис в своих выходных данных, этот синтаксис:

```
 [ЭТАП ЗАГРУЗКИ][С ЧЕЙ СТОРОНЫ ЗАГРУЗКА (СЕРВЕР/КЛИЕНТ)][ТИП] <сообщение>

```

Когда вы запустили *Minecraft* со скриптом *hello.zs* в файле *crafttweaker.log* вы увидите следующие.

```
[PREINITIALIZATION][CLIENT][INFO] Hello world!

```

###  **Комментарии**

Комментарии могут быть использованы для того, чтобы сделать ваши файлы сценариев более удобочитаемыми и понятными!
ZenScript поддерживает 3 типа комментариев:

Однострочный комментарий: ***// Я однострочный комментарий!***
Альтернативный однострочный комментарий: ***# Я тоже однострочный комментарий!***
Многострочный:

```
/\* Это
я
многострочный комментарий! \*/

```

###  **Переменные**

В CraftTweaker существует 2 переменные ***val*** и ***var***

***val*** - Динамическая переменная, она может менять свое значение

***var*** - Статическая переменная, она не может менять свое значение

```
var Имя Переменной = значение;
val Имя Переменной = значение;

```

Вы везде можете использовать как ***val*** так и ***var***.

###  **Массивы**

***Массив*** - это список, содержащий несколько элементов одного и того же вида.

#### ***Объявление массивов***

Они объявляются с помощью [ и ].

***Важно***: вы должны инициализировать массивы для чего-то, даже если это пустой массив.

***var floatArray as float [];*** синтаксических ошибок не будет, но при перезагрузке вашей игры вы получите сообщение об ошибке, и ваш скрипт не будет работать.

Вместо этого инициализируйте пустые массивы, подобные этому ***var floatArray, as float [] = [];***

```
//Массив хранит "Hello" и "World"
val stringArray = ["Hello", "World"] as string[];

//Массив хранит 1-3
val intArray = [1,2,3] as int[];

```

Вы, конечно, заметили, что ко всем массивам здесь добавляется оператор as.
Это связано с тем, что ZenScript иногда не может предсказать, к какому типу относятся элементы в массиве. Это может быть причиной появления странных журналов ошибокKe!
Лучше сразу привести массив к нужному типу данных чем потом сожалеть и гадать в из-за случилась ошибка.

Кроме того, если вы приводите к непримитивным типам (все, кроме string, int, bool и т.п), обязательно импортируйте соответствующий пакет и обязательно сделайте это в верхней части скрипта:

```
import crafttweaker.item.IItemStack;
val IArray = [<minecraft:gold\_ingot>, <minecraft:iron\_ingot>] as IItemStack[];

```

#### **Вложенные массивы**

Вы можете размещать массивы в массивах.

```
val stringArray1 = ["Привет","Мир"] as string[];
val stringArray2 = ["Я","самый"] as string[];
val stringArray3 = ["крутой","скриптер"] as string[];
val stringArrayAll = [stringArray1,stringArray2,stringArray3,["Saudade Studio","!"]] as string[][];

```

#### **Ссылка на элементы в массиве**

Вы можете сослаться на элемент в массиве, используя его место в списке. Первый элемент в массиве - № 0, 2-й - №1 и так далее.
Если вы хотите сослаться на элемент во вложенном массиве, вам понадобятся два или более референтов, так как каждый удаляет один слой списков.

```
/\*
stringArray[0] is "Hello"
stringArray[1] is "World"
stringArray[2] is "I"
stringArray[3] is "am"
\*/
val stringArray = ["Hello","World","I","am"] as string[];

//prints "Hello"
print(stringArray[0]);

//Nested Arrays
val stringArray1 = ["Hello","World"] as string[];
val stringArray2 = ["I","am"] as string[];
val stringArray3 = ["a","beautiful"] as string[];
val stringArrayAll = [stringArray1,stringArray2,stringArray3,["Scripter","!"]] as string[][];

/\*
stringArrayAll[0] is ["Hello","World"]
stringArrayAll[1] is ["I","am"]
stringArrayAll[2] is ["a","beautiful"]
stringArrayAll[3] is ["Scripter","!"]

stringArrayAll[0][0] is "Hello"
stringArrayAll[0][1] is "World"
etc.
\*/

//prints "World"
print(stringArrayAll[0][1]);

```

#### **Ассоциативные массивы**

***Ассоциативный*** массив (иногда также называемый картой или словарем) похож на обычный массив в том смысле, что он способен хранить несколько записей. Однако, в отличие от массивов, вы можете выбрать, какого типа вы хотите, чтобы индекс, или (как мы называем его в maps) ключ, был!

##### **Объявление ассоциативного массива**

```
val myAssocArray = {
 dirt : <minecraft:dirt>,
 gold : <minecraft:gold\_ingot>
} as IItemStack[string];

```

Давайте разберемся с этим.

* ***val myAssocArray*** : стандартное объявление переменной
* ***{*** : это ассоциативный массив, сэр!
* ***dirt*** : <minecraft:dirt> создаём ключ <minecraft:dirt> с типом ***string*** Грязь
* ***,*** : подожди, это еще не все
* ***gold*** : <minecraft:gold\_ingot> создаём ключp <minecraft:gold\_ingot> с типом данных ***string*** Золото
* ***}*** : мы достигли конца цепочки, сэр!
* ***as IItemStack[string]; :***  это ассоциативный массив, который использует строки в качестве индексов и ItemStack в качестве значений.

Хорошо, итак, о чем мне нужно думать при их использовании?

* Вы можете использовать практически любой тип, доступный в ***Zenscript***, в качестве ключа или значения.
* Вы не можете использовать переменные для объявления ключа в первоначальном объявлении (том, которое использует {}), поскольку открытый текст интерпретируется как строка!

##### **Ссылка на элементы внутри ассоциативного массива.**

Вы ссылаетесь на элементы внутри ассоциативного массива так же, как вы ссылаетесь на элементы внутри обычного массива: ***Array[index]***

Единственная разница в том, что на этот раз вам не обязательно использовать целое число в качестве индекса, но каким бы типом вы ни объявили свой массив!

```
val dirt = <minecraft:dirt>;
val assocArray = {
 <minecraft:dirt> : "Это я"
} as string[IItemStack];

//array[index]
print(assocArray[<minecraft:dirt>]);

//Вы также можете использовать переменные здесь, при условии, что переменная имеет правильный тип
print(assocArray[dirt]);

```

Есть один особый случай, когда вы используете строки в качестве индексов:

В этом случае вы также можете использовать memberGetter следующим образом:

```
val assocWithStrings = {
 //вы можете использовать "", если хотите
 "one" : "1",

 //но ты не обязан
 two : "2"
} as string[string];

//Вы можете либо использовать memberGetter
print(assocWithStrings.one);

//Или стандартный получатель индекса
print(assocWithStrings["two"]);

```

##### **Манипулирование элементами внутри ассоциативного массива**

Как и в случае с массивами, вы можете манипулировать элементами внутри ассоциативного массива с помощью ***array[index] = newValue***

Однако есть одно существенное отличие:

В то время как массивы имеют фиксированный размер, карты этого не делают. Это означает, что вы всегда можете добавить запись, установив индекс, который ранее не был установлен!

```
val changingArray = {
 <minecraft:dirt> : "это я",
 <minecraft:gold\_ingot> : "и я ненавижу это"
} as string[IItemStack];

val gg = <minecraft:gold>;

//Переопределяет значение gold\_ingot
changingArray[gg] = "и мне это нравится";

//добавляет новую запись
changingArray[<minecraft:grass>] = "Сила!";

```

##### **Извлечение ключа ассоциативного массива и наборов записей**

***Набор ключей*** - это массив, содержащий все ключи карты.

***Набор значений*** - это массив, содержащий все значения карты.

***entrySet*** - это массив, содержащий все записи карты (см. ниже).

```
myAssocArray.keySet //keySet
myAssocArray.keys //keySet
myAssocArray.values //valueSet
myAssocArray.valueSet //valueSet
myAssocArray.entrySet //entrySet

```

##### **Перебор ассоциативного массива**

Есть два итератора, которые позволяют вам выполнять итерации по ассоциативному массиву:

* Ключ-итератор: перебирает ключи, использует одну переменную
* Ключ-значение-итератор: выполняет итерацию по ключам и значениям, использует две переменные

Давайте добавим ассоциативный массив, в котором хранятся рецепты крафта:

* Ключи должны быть результатом обработки в виде ***IItemStack***
* Значения должны быть ингредиентами для приготовления в качестве ***IIngredient***
* Мы будем использовать ключ-итератор, который построен следующим образом: ***for key in assocArray {doSth;}***
* Мы также будем использовать итератор ключ-значение, который построен следующим образом: ***for key, value in assocArray {doSth;}***

```
import crafttweaker.item.IItemStack;
import crafttweaker.item.IIngredient;

val dirt = <minecraft:dirt>;
val recipeMapShaped = {
 <minecraft:grass> : [[dirt, dirt, dirt],[dirt, dirt, dirt],[dirt, dirt, dirt]],
 <minecraft:gold\_ingot> : [[dirt, dirt, dirt],[dirt, <minecraft:gold\_ingot>, dirt],[dirt, dirt, dirt]]
} as IIngredient[][][IItemStack];

recipeMapShaped[dirt] = [[dirt, dirt, dirt],[dirt, null, dirt],[dirt, dirt, dirt]];

//ключевыми будут grass, goldIngot, dirt
for key in recipeMapShaped {
 recipes.addShaped(key, recipeMapShaped[key]);
}

//ключами будут grass, goldIngot, dirt, а переменные - рецепты для них
for key, value in recipeMapShaped {
 recipes.addShaped(key, value);
}

```

##### **Запись ZenType**

Запись на карте состоит из ключа и значения.

В настоящее время единственный способ получить такой объект - это использовать метод entrySet карты.

Вы можете использовать геттеры, чтобы получить key и value

```
//Заменить карту ссылкой на существующую карту/ассоциативный массив
val myEntry = map.entrySet[0];

myEntry.key; //Возвращает ключ записи.
myEntry.value; //Возвращает значение записи.

```

###  **Циклы**

***Цикл*** - это функция, которая повторяется сама по себе. Вы можете использовать циклы для применения действия ко всем элементам массива

#### **Цикл For**

Основное использование цикла ***for*** - это итерация по массиву. Повторение означает выполнение действия со всеми элементами массива.
Вы можете использовать ключевое слово ***break***, чтобы преждевременно прервать цикл.

```
import crafttweaker.item.IItemStack;

val IArray = [<minecraft:dirt>,<minecraft:planks>,<minecraft:diamond>] as IItemStack[];
val JArray = [<minecraft:grass>,<minecraft:log>,<minecraft:gold\_ingot>] as IItemStack[];
val KArray = [<minecraft:wooden\_axe>,<minecraft:golden\_shovel>,<minecraft:emerald>] as IItemStack[];

//for [IntegerName, ] elementName in IArray {code}

for item in IArray {
 //Определяет переменную "item" для каждого элемента IArray (т.е. <minecraft:грязь>,<minecraft:доски>,<minecraft:алмаз>)
 //Просто используйте эту переменную сейчас!
 recipes.remove(item);
}

for i, item in IArray {
 //определяет переменную "i" с номером каждого элемента массива (т.е. 0,1,2,...)
 //определяет переменную "item" для каждого элемента массива (т.е. <minecraft:грязь>,<minecraft:доски>,<minecraft:алмаз>)
 //Просто используйте эти переменные сейчас!

 //Крафт из IArray с использованием предметов JArray и KArray (например, грязь с травой и деревянным топором, доски с деревом и золотой лопатой, алмаз с золотым слитком и изумрудом)
 recipes.addShapeless(item,[JArray[i],KArray[i]]);
}

for i in 0 to 10 {
 //определяет переменную "i" с каждым числом от 0 до 9 (т.е. 0,1,2,...,8,9)
 print(i);
}

for i in 10 .. 20 {
 //определяет переменную "i" с каждым числом от 10 до 19 (т.е. 10,11,12,...,18,19)
 print(i);
}

for item in loadedMods["minecraft"].items {
 //определяет переменную "item" для каждого предмета, добавленного модом с модифицированным "minecraft", и удаляет его рецепт изготовления
 recipes.remove(item);
}

```

#### **Цикл While**

Цикл ***while*** выполняет данный код до тех пор, пока заданное условие не примет значение ***true***.
В качестве альтернативы вы можете остановить его, используя ключевое слово ***break***

```
var i = 0;

//Выведет 0 - 9, потому что на следующей итерации значение i < 10 равно false, так как тогда i равно 10.
while i < 10 {
 print(i);
 i += 1;
}

print("После цикла: " + i);

//Выведет 10 - 6, потому что в итерации после этого i == 5 и это сломается.
while (i > 0) {
 if i == 5
 break;
 print(i);
 i -= 1;
}

print("После цикла 2: " + i);

for k in 1 .. 10 {
 if (k == 5)
 break;
 print(k);
}

```

#### **Добавление элементов в массив**

Хотя это не рекомендуется делать, можно добавить некоторые объекты в массивы.
Вы можете добавлять только отдельные объекты в массив, вы не можете добавлять два массива.
Вы используете оператор + для добавления массива:

```
import crafttweaker.item.IItemStack;

val iron = <minecraft:iron\_ingot>;
var array as IItemStack[] = [iron, iron, iron];

array += iron;
for item in array {
 print(item.displayName);
}

```