Отрисовывать блоки с кастомыми моделями через каллбек крайне неэффективно и в большинстве случаев вызывает сильные лаги. Потому, хоть такая возможность и существует, она крайне ситуативна и будет рассмотрена в другой раз.
ICRender представляет из себя систему, позволяющую заранее задать то, как будет выглядеть модель при разных условиях. Поскольку модель описывается заранее, а дальше все расчёты происходят в нативном коде, модели ICRender дают крайне малую нагрузку.
Используя модели ICRender для обработки простых условий и их маппинг на координаты, который был рассмотрен ранее, можно создать любой внешний вид блока и в абсолютном большинстве случаев заменить прямой каллбек рендера.
Модель ICRender является набором статических моделей, рассмотренных ранее, и условий, при которых они видимы. Чтобы создать пустую модель используется конструктор:
var icRender = new ICRender.Model();
Для добавления статичной модели (они были рассмотрены ранее) в модель ICRender используется метод addEntry(model), отдающий объект, позволяющий установить условия отрисовки:
var model = new BlockRender.BlockModel(); … modify model ... var entry = icRender.addEntry(model);
Для установки условий отрисовки используется метод полученного объекта setCondition(condition), где condition - объект условия, которые будут рассмотрены далее:
var entry = icRender.addEntry(model); entry.setCondition(…); // короткая запись
icRender.addEntry(model).setCondition(…);
Если условие не было установлено, то данная статичная модель будет всегда видима.
Группы блоков в ICRender нужны для создания условий, с ними будут сверяться блоки на каких-либо координатах при проверке условий.
Для создания группы используются методы:
ICRender.getGroup("name") - возвращает группу, зарегистрированную под данным именем, если такой нет, создает новую и регистрирует. Имя нужно для удобства доступа и совместимости между модами (К примеру, все блоки, к которым подключаются провода в Industrial Craft зарегистрированы в группе с именем'"icwire")'
ICRender.getUnnamedGroup() - создает и возвращает новую группу без имени, используется для создания локальных группМетоды группы блоков:
group.add(id, data) - добавляет блок с данным id и data в группу, если вместо data передано число -1, в группу будут добавлены все блоки с этим id group.getName() - возвращает имя группы
Любое из перечисленных условий может быть передано как параметр condition в описанных ранее и далее функциях. Каждое условие может быть истринным или ложным, при отрисовке модели ICRender, для того, чтобы какая то статичная модель была видима, у нее не должно быть условий, или условие, переданное в setCondition должно выполняться.
ICRender.BLOCK(x, y, z, group, exclude) - условие проверки одного блока на координатах (координаты задаются относительно позиции блока, к примеру, позиция на 1 блоквыше будет задаваться как 0, 1, 0). Если параметр exclude false, условие выполнится, если данная группа содержит блок на данных координатах, а если exclude true, то если группа его не содержит.
ICRender.NOT(condition) - логический оператор НЕТ от данного условия, выполняется, если данное условие не выполняется.
ICRender.AND(condition1, condition2, …) - логический оператор И, принимает 2 или больше условий на вход, выполняется, если все эти условия тоже выполняются.
ICRender.OR(condition1, condition2, …) - логический оператор ИЛИ, принимает 2 или больше условий на вход, выполняется, если хотя бы одно из условий тоже выполняется.
Будет рассмотрено достаточно простое и распространенное применение ICRender - создание блока наподобие провода или трубы, который может соединяться с соседними такими же со всех сторон.
var id = … // id блока провода var width = 0.5 // толщина провода
var group = ICRender.getGroup("testWire"); // группа блоков
group.add(id, -1); // добавим сам провод в группу
/* Данные про то, какие боксы должны быть видны в зависимости от того, есть на относительных координатах блок из группы или нет. Каждый объект в массиве — это данные для модели и условия: side - относительные координаты, box - координаты бокса. Можно без проблем реализовать модель без этого массива, но так меньше кода и есть разделение между данными модели и ее созданием.*/
var boxes = [
{side: [1, 0, 0], box: [0.5 + width / 2, 0.5 - width / 2, 0.5 - width / 2, 1, 0.5 + width / 2, 0.5 + width / 2]},
{side: [-1, 0, 0], box: [0, 0.5 - width / 2, 0.5 - width / 2, 0.5 - width / 2, 0.5 + width / 2, 0.5 + width / 2]},
{side: [0, 1, 0], box: [0.5 - width / 2, 0.5 + width / 2, 0.5 - width / 2, 0.5 + width / 2, 1, 0.5 + width / 2]},
{side: [0, -1, 0], box: [0.5 - width / 2, 0, 0.5 - width / 2, 0.5 + width / 2, 0.5 - width / 2, 0.5 + width / 2]},
{side: [0, 0, 1], box: [0.5 - width / 2, 0.5 - width / 2, 0.5 + width / 2, 0.5 + width / 2, 0.5 + width / 2, 1]},
{side: [0, 0, -1], box: [0.5 - width / 2, 0.5 - width / 2, 0, 0.5 + width / 2, 0.5 + width / 2, 0.5 - width / 2]}
];
var model = new ICRender.Model(); // создаем новую модель
model.addEntry(new BlockRenderer.Model(0.5 - width / 2, 0.5 - width / 2, 0.5 - width / 2, 0.5 + width / 2, 0.5 + width / 2, 0.5 + width / 2, id, 0));
// добавляем центральный бокс, который виден всегда
for(var i in boxes){
// Получаем относительные координаты и координаты бокса из данных выше
var box = boxes[i].box;
var side = boxes[i].side;
/* одним выражением создаем статичную модель из одного бокса (используем текстуру блока с нашим id), добавляем ее в модель ICRender и устанавливаем условие отрисовки - должен быть блок из созданной ранее группы на данных относительных координатах.*/
model.addEntry(new BlockRenderer.Model(box[0], box[1], box[2], box[3], box[4], box[5], id, 0))
.setCondition(new ICRender.BLOCK(side[0], side[1], side[2], group, false));
}
// устанавливаем созданную модель блоку
BlockRenderer.setStaticICRender(id, -1, model);