Песочница/Pok/3: различия между версиями

мНет описания правки
Нет описания правки
 
(не показана 291 промежуточная версия 4 участников)
Строка 1: Строка 1:
{{#invoke:CategoryMenu|main
{{docpage}}{{TOC hidden}}
|category1 = Категория 1
{{OnLua|Сущность|module1=Сущность|module2=Сущность/поля|module3=GetField}}
|category1-paragraph1 = Пункт 1.1
 
|category1-paragraph2 = Пункт 1.2
Модульный набор {{tl|Модуль:Сущность}} + {{tl|Модуль:Сущность/поля}} + {{tl|Модуль:GetField}} предназначен для:
|category1-paragraph3 = Пункт 1.3
* автоматической сборки карточек сущностей (компонентов и прототипов) по их ID;
|category1-paragraph1-content = Контент для пункта 1.1
* описания полей в шаблонах компонентов (какие поля идут в карточку, как подписаны);
|category1-paragraph2-content = Контент для пункта 1.2
* удобного доступа к данным из JSON (как простыми значениями, так и готовыми вызовами шаблонов).
|category1-paragraph3-content = Контент для пункта 1.3
 
|category2 = Категория 2
Ниже описан общий принцип работы и отдельные режимы.
|category2-paragraph1 = Пункт 2.1
 
|category2-paragraph2 = Пункт 2.2
== Общий принцип работы ==
|category2-paragraph3 = Пункт 2.3
* В шаблонах компонентов/прототипов (<code>Template:Component/...</code>, <code>Template:prototype/...</code>) через {{tl|Модуль:Сущность/поля}} описываются поля:
|category2-paragraph1-content = Контент для пункта 2.1
** '''лейблы''' (<code>cardLabel_*</code>) и '''содержимое''' (<code>cardContent_*</code>), заголовки (<code>title_*</code>) и т. п.;
|category2-paragraph2-content = Контент для пункта 2.2
** '''мета‑информация''' о том, какие ключи доступны для <code>card</code> / <code>title</code> и в каком порядке.
|category2-paragraph3-content = Контент для пункта 2.3
* {{tl|Модуль:Сущность}} по ID сущности:
** находит связанные с ней компоненты и прототипы по JSON‑данным;
** для каждого компонента/прототипа читает шаблоны и метаданные;
** собирает все поля в единую структуру;
** формирует один вызов карточки <code><nowiki>{{карточка/сущность|...}}</nowiki></code> (и блоки заголовков).
* Внутри полей можно писать вики‑параметры <code>{{{...}}}</code> и вызывать дополнительные модули.
* {{tl|Модуль:GetField}} даёт доступ к JSON‑данным на низком уровне:
** как «расплющенный» набор параметров (<code>flattenField</code>);
** как отдельные значения (<code>get</code>);
** как готовые вызовы шаблонов с нужными параметрами (<code>getTpl</code>, <code>getTplProto</code>).
 
== Модуль: Сущность/поля ==
Шаблоны компонентов используют модуль <code>Сущность/поля</code> для объявления полей, которые будут собираться в карточку.
 
Пример шаблона компонента:
 
<pre>
{{#invoke:Сущность/поля|main
|cardLabel_Стоимость  = [[Стоимость]]
|cardContent_Стоимость = '''{{{price}}}'''
}}
}}
{{#css:
</pre>
.categories {
 
    display: flex;
Другой компонент может добавлять тот же ключ:
    justify-content: center;
 
    padding: 10px;
<pre>
    background-color: #313138;
{{#invoke:Сущность/поля|main
    border-bottom: 1px solid #ccc;
|cardContent_Стоимость  = '''{{{superPrice}}}'''
}}
</pre>
 
Особенности:
* Пара <code>cardLabel_<Ключ></code> / <code>cardContent_<Ключ></code> описывает одну строку карточки (лейбл и содержимое).
* Если несколько шаблонов дают один и тот же <code>cardContent_Ключ</code>, содержимое '''объединяется''', а лейбл берётся первый непустой.
* То же относится к другим режимам, перечисленным в мета‑JSON шаблона (разделы <code>card</code>, <code>title</code> и т. п.), которые читает {{tl|Модуль:Сущность}}.
 
== Модуль: Сущность ==
 
=== p.get: основная сборка карточки ===
Вызов:
 
<pre>
{{#invoke:Сущность|get
| <ID или список ID>
| blacklist=...
| whitelist=...
| ignoreComponents=...
| ignorePrototypes=...
}}
</pre>
 
* '''1‑й параметр''' — <code>id</code> или список <code>id</code> через запятую.
* По этому ID модуль находит:
** '''компоненты''' из <code>component.json</code>;
** '''прототипы''' из <code>prototype.json</code>;
и для каждого — соответствующие шаблоны <code>Template:component/...</code> / <code>Template:prototype/...</code>.
* Шаблоны описывают свои поля через <code>Сущность/поля</code>.
 
После сборки модуль:
* формирует один вызов <code><nowiki>{{карточка/сущность|...}}</nowiki></code> со всеми разделами и полями;
* дополняет выход при необходимости (блоки title и т. п.);
* прогоняет результат через <code>frame:preprocess</code>, чтобы отрендерить разметку.
 
Параметры фильтрации:
* {{пм|blacklist}} — список <code>режим_Ключ</code> через запятую, чтобы исключить поле:
** пример: <code>blacklist=card_Наносит повреждения,title_Что‑то</code>;
* {{пм|whitelist}} — наоборот, список разрешённых <code>режим_Ключ</code>, остальные игнорируются;
* {{пм|ignoreComponents}} / {{пм|ignoreComponent}} — список имён компонентов через запятую, которые полностью игнорируются для этого вызова;
* {{пм|ignorePrototypes}} / {{пм|ignorePrototype}} — аналогично для прототипов.
 
Пример простой сборки (через шаблон‑обёртку):
 
<pre>
{{Сущность/карточка|MyEntityId}}
</pre>
 
где в шаблоне <code>Сущность/карточка</code> внутри:
 
<pre>
{{#invoke:Сущность|get|{{{1}}}}}
</pre>
 
=== p.preview: предпросмотр полей конкретного шаблона ===
Используется для проверки, что компонент/прототип правильно описал свои поля.
 
<pre>
{{#invoke:Сущность|preview
| Component/meleeWeapon
}}
</pre>
 
* Показывает, какие <code>card</code> / <code>title</code>‑поля объявлены в <code>Template:Component/meleeWeapon</code>.
* Удобно при разработке шаблонов компонентов.
 
=== p.jsonList: вывод JSON в виде списка ===
Режим похож на стандартный <code>arraymap</code>, но работает с JSON.
 
<pre>
{{#invoke:Сущность|jsonList
| <json или {{{...}}}>
| type = list / enum
| prefix = *
| sep = :
| key_pattern = (.*)
| key_replace = \1
| value_pattern = (.*)
| value_replace = \1
}}
</pre>
 
Примеры JSON:
 
<pre> <!-- <syntaxhighlight lang=json> -->
{
  "Blunt": 10,
  "Slash": 5
}
}
</pre> <!-- </syntaxhighlight> -->
или
<pre> <!-- <syntaxhighlight lang=json> -->
["Knife", "Sword", "Bat"]
</pre> <!-- </syntaxhighlight> -->
Основные опции:
* {{пм|type}}:
** <code>list</code> — список строк (с префиксом, например <code>* </code>);
** <code>enum</code> — перечисление через запятую (<code>A, B, C</code> без префикса).
* {{пм|prefix}} — префикс строки списка (по умолчанию <code>* </code>).
* {{пм|sep}} — разделитель для <code>ключ: значение</code> (по умолчанию <code>: </code>).
* {{пм|key_pattern}} / {{пм|key_replace}} — regex и замена для ключей.
* {{пм|value_pattern}} / {{пм|value_replace}} — regex и замена для значений.
Дополнительно:
* в шаблоне замены поддерживаются:
** <code>\1</code> — собственное значение (ключ или значение);
** <code>\2</code> в <code>value_replace</code> — '''сырой ключ''' (после <code>key_pattern</code>, но до <code>key_replace</code>);
** <code>\2</code> в <code>key_replace</code> — итоговое отформатированное значение (после <code>value_replace</code>).
Пример, где сначала форматируем тип урона, а затем подставляем его в описание:
<pre>
{{#invoke:Сущность|jsonList
| {{{damage.types}}}
| type = enum
| key_replace = <nowiki>\1</nowiki>              <!-- "Blunt" -->
| value_replace = <nowiki>'''\1''' \2</nowiki>  <!-- "'''10''' Blunt" -->
}}
</pre>
=== p.json: превращение JSON в вызовы шаблонов ===
Режим для случаев, когда в JSON лежит список эффектов/объектов, и нужно по каждому вызвать отдельный шаблон.
<pre>
{{#invoke:Сущность|json
| <json или {{{...}}}>
| <путь_к_шаблону>
}}
</pre>
* '''1‑й параметр / <code>json=</code>''' — строка JSON.
* '''2‑й параметр / <code>template=</code>''' — путь к шаблону, например <code>Component/adjustPlant</code>.
Ожидаемый формат JSON‑массива:
<pre> <!-- <syntaxhighlight lang=json> -->
[
  {
    "!type:PlantAdjustNutrition": {
      "amount": 0.1
    }
  },
  {
    "!type:PlantAdjustWeeds": {
      "amount": 2
    }
  },
  {
    "!type:PlantAdjustPests": {
      "amount": 2
    }
  }
]
</pre> <!-- </syntaxhighlight> -->
Для каждого элемента создаётся вызов:


.categories div {
<pre>
    cursor: pointer;
{{Component/adjustPlant
    padding: 10px 20px;
|id=!type:PlantAdjustNutrition
    margin: 0 10px;
|amount=0.1
    border: 1px solid #ccc;
}}
    background-color: #4f4f4f;
{{Component/adjustPlant
}
|id=!type:PlantAdjustWeeds
|amount=2
}}
{{Component/adjustPlant
|id=!type:PlantAdjustPests
|amount=2
}}
</pre>
 
Особенности:
* Если JSON — объект вида <code>{ "id1": {...}, "id2": {...} }</code>, происходит аналогичный проход по парам <code>ключ → объект</code>.
* Все вызовы склеиваются через перевод строки и прогоняются через <code>frame:preprocess</code>, поэтому внутри шаблона можно использовать любую вики‑разметку.
 
== Модуль: GetField ==
Модуль <code>GetField</code> используется для доступа к тем же JSON‑данным <code>.../data</code>, но на более низком уровне.
 
=== p.flattenField: расплющивание записи в параметры ===
<pre>
{{#invoke:GetField|flattenField
| <id>
| <путь_к_json_странице>
}}
</pre>
 
Например:
 
<pre>
{{#invoke:GetField|flattenField
| MyEntityId
| component/item.json
}}
</pre>
 
Возвращает строку вида:
 
<pre>
damage.types={"Blunt":10}|wieldSound=someSound|...
</pre>
 
Особенности:
* Вложенные объекты кодируются в JSON и заворачиваются в <code><nowiki><nowiki></nowiki></code>, чтобы их можно было безопасно передавать как параметр.
* Массивы кодируются в JSON без <code><nowiki><nowiki></nowiki></code>, чтобы удобно обрабатывать их модулями вроде <code>Сущность.jsonList</code>.
 
Этот режим используется внутри <code>GetField.getTpl</code> и других обёрток.
 
=== p.get: получение значения по пути ===
<pre>
{{#invoke:GetField|get
| <id или пусто для "default">
| <путь_к_json_странице>
| <ключ.с.точками>
}}
</pre>
 
Примеры:
 
<pre>
{{#invoke:GetField|get
| MyEntityId
| component/item.json
| damage.types
}}
</pre>


.main-container {
Если в JSON:
    display: flex;
    width: 100%;
}


/* Меню слева */
<pre> <!-- <syntaxhighlight lang=json> -->
.menu-container {
"damage": {
    width: 200px;
  "types": {
    padding: 10px;
     "Blunt": 10
     border-right: 1px solid #ccc;
  }
    background-color: #313138;
}
}
</pre> <!-- </syntaxhighlight> -->


.menu div {
то результатом будет:
    cursor: pointer;
    padding: 10px;
    border: 1px solid #ccc;
    margin-bottom: 5px;
    background-color: #4f4f4f;
}


.content {
<pre>
    padding: 10px;
{"Blunt":10}
    width: 100%;
</pre>
    background: #46464d;
}


.content div {
то есть:
    display: none;
* для таблиц модуль пытается сделать <code>mw.text.jsonEncode(v)</code> и вернуть JSON‑строку;
}
* для простых значений возвращается строка <code>tostring(v)</code>.


.content .active {
Если <code>keyPath</code> пуст, возвращается весь объект (как JSON).
    display: block;
}


.menu {
=== p.getTpl: вызов шаблона по данным JSON ===
    display: none; /* Скрываем меню, если категория не выбрана */
<pre>
}
{{#invoke:GetField|getTpl
| <id>
| <путь_к_json_странице>
| <путь_к_шаблону>
}}
</pre>


.menu.active {
Пример:
    display: block; /* Отображаем активное меню */
}


.menu .active {
<pre>
    background-color: #616161; /* Выделение активного пункта меню */
{{#invoke:GetField|getTpl
}
| MyEntityId
| component/item.json
| Component/meleeWeapon
}}
}}
</pre>


__TOC__
Работа:
<div class="custom-heading">1</div>
* внутри вызывает <code>flattenField</code>, получая строку <code>key=value|...</code>;
<h2>2</h2>
* формирует строку вида:
<h2>3</h2>


<pre>
{{Component/meleeWeapon
|id=MyEntityId
|damage.types=...
|...
}}
</pre>


{| class="table-container"
* и прогоняет её через <code>frame:preprocess</code>, возвращая итоговый рендер.
! class="header-cell" | //
 
! class="header-cell" | Строители
Это удобный способ «подключить» шаблон компонента к данным из JSON без ручного перечисления параметров.
! class="header-cell" | Хищники
! class="header-cell" | Воины
! class="header-cell" | Плеваки
! class="header-cell" style="width: 10%;" | Время для эволюции
|-
! class="data-cell" | T0
! class="separator" | {{tooltip|[[File:CMXenoLesserDrone.png|128px]]|Эволюционирует в:|Не имеет эволюций<br>}}<br><span class="text-cell">[[CM:Младший дрон|Младший дрон]]</span>
! colspan="2" class="separator" | {{tooltip|[[File:CMXenoHugger.png|128px]]|Откладывает Грудолома[[File:CMXenoLarva.png|64px]]<br>}}<br><span class="text-cell">[[CM:Лицехват|Лицехват]]</span>
! colspan="2" class="separator" style="text-align:left;" id="source-node1" class="source"| {{tooltip|[[File:CMXenoLarva.png|128px]]|Эволюционирует в:|[[File:CMXenoDrone.png|64px]] Трутень<br>[[File:CMXenoRunner.png|64px]] Бегун<br>[[File:CMXenoDefender.png|64px]] Защитник<br>[[File:CMXenoSentinel.png|64px]] Часовой<br>}}<br><span class="text-cell">[[CM:Грудолом|Грудолом]]</span>
|-
! class="data-cell" | T1
! class="separator" id="target-node1" class="target" id="source-node2" class="source" | {{tooltip|[[File:CMXenoDrone.png|128px]]|Эволюционирует в:|[[File:CMXenoHivelord.png|64px]] Лорд улья<br>[[File:CMXenoQueen.png|64px]] Королева<br>}}<br><span class="text-cell">[[CM:Трутень|Трутень]]</span>
! class="separator" id="target-node1" class="target" | {{tooltip|[[File:CMXenoRunner.png|128px]]|Эволюционирует в:|[[File:CMXenoLurker.png|128px]] Охотник<br>}}<br><span class="text-cell">[[CM:Бегун|Бегун]]</span>
! class="separator" id="target-node1" class="target" | {{tooltip|[[File:CMXenoDefender.png|128px]]|Эволюционирует в:|[[File:CMXenoWarrior.png|64px]] Воин<br>}}<br><span class="text-cell">[[CM:Защитник|Защитник]]</span>
! class="separator" id="target-node1" class="target" | {{tooltip|[[File:CMXenoSentinel.png|128px]]|Эволюционирует в:|[[File:CMXenoSpitter.png|64px]] Плевака<br>}}<br><span class="text-cell">[[CM:Часовой|Часовой]]</span>
! class="separator" | 5 минут
|-
! class="data-cell" | T2
! class="separator" id="target-node2" class="target" | {{tooltip|[[File:CMXenoHivelord.png|128px]]|Эволюционирует в:|Не имеет эволюций<br>}}<br><span class="text-cell">[[CM:Лорд улья|Лорд улья]]</span>
! class="separator" | {{tooltip|[[File:CMXenoLurker.png|128px]]|Эволюционирует в:|[[File:Rooney.png|64px]] Руни<br>}}<br><span class="text-cell">[[CM:Охотник|Охотник]]</span>
! class="separator" | {{tooltip|[[File:CMXenoWarrior.png|128px]]|Эволюционирует в:|[[File:CMXenoCrusher.png|64px]] Крушитель<br>[[File:CMXenoPraetorian.png|64px]] Преторианец<br>}}<br><span class="text-cell">[[CM:Воин|Воин]]</span>
! class="separator" | {{tooltip|[[File:CMXenoSpitter.png|128px]]|Эволюционирует в:|[[File:CMXenoBoiler.png|128px]] Бойлер<br>}}<br><span class="text-cell">[[CM:Плевака|Плевака]]</span>
! class="separator" | 9 минут
|-
! class="data-cell" | T3
! class="separator" |
! class="separator" | {{tooltip|[[File:Rooney.png|128px]]|Эволюционирует в:|Не имеет эволюций<br>}}<br><span class="text-cell">[[CM:Руни|Руни]]</span>
! class="separator" | {{tooltip|[[File:CMXenoCrusher.png|128px]]|Эволюционирует в:|Не имеет эволюций<br>}}<br><span class="text-cell">[[CM:Крушитель|Крушитель]]</span>
! class="separator" | {{tooltip|[[File:CMXenoBoiler.png|128px]]|Эволюционирует в:|Не имеет эволюций<br>}}<br><span class="text-cell">[[CM:Бойлер|Бойлер]]</span>
! class="separator" | 9 минут
|-
! class="data-cell" | T4
! id="target-node2" class="target" | {{tooltip|[[File:CMXenoQueen.png|128px]]|Эволюционирует в:|Не имеет эволюций<br>}}<br><span class="text-cell">[[CM:Королева|Королева]]</span>
!
!
!
! 9 минут
|}
<!-- CSS -->
<div class="customCSS" style="display:none">
svg {
position: absolute;
pointer-events: none;
z-index: 1;
}
/* Общие стили для таблицы */
.table-container {
max-width: 100%;
margin: auto;
padding: 5px;
overflow-x: auto;
color: white;
font-weight: bold;
border-radius: 10px;
width: 100%;
border-collapse: collapse;
white-space: nowrap;
padding: 100px;
text-align: center;
background-color: #2B1438;
border: 1px solid black;
}


/* Стили для ячеек заголовков */
=== p.getTplProto: вызов шаблона по прототипам ===
.header-cell {
<pre>
padding: 10px;
{{#invoke:GetField|getTplProto
border: 1px solid #000;
| <searchId>
background-color: #4B285B;
| <protoId>
}
| <путь_к_шаблону>
}}
</pre>


/* Стили для ячеек данных */
* Ищет в <code>prototype.json</code> все записи, где <code>protoId</code> встречается у <code>searchId</code>.
.data-cell {
* Для каждого найденного ID вызывает <code>getTpl</code> и возвращает все вызовы, склеенные через перевод строки и отрендеренные.
padding: 5px;
border: 1px solid #000;
background-color: #4B285B;
}


/* Стили для разделительных линий */
Используется для случаев, когда сущность использует '''несколько''' прототипов одного типа, и нужно вывести по одному шаблону на каждый прототип.
.separator {
border-bottom: 2px dashed #90449C;
}


/* Стили для текста внутри ячеек */
== Типичный рабочий поток ==
.text-cell {
# В JSON‑файлах (<code>component.json</code>, <code>prototype.json</code> и др.) описываются сущности и связи компонент/прототипов.
display: inline-block;
# Для каждого компонента/прототипа создаются шаблоны <code>Template:Component/...</code>, <code>Template:prototype/...</code>, которые:
margin: 10px;
#* вызывают <code><nowiki>{{#invoke:Сущность/поля|main ...}}</nowiki></code> для описания полей карточки;
padding: 7px 12.5px;
#* при необходимости используют <code>GetField</code> / <code>Сущность.jsonList</code> / <code>Сущность.json</code> для форматирования сложных JSON‑полей.
border-radius: 8px;
# Для вывода карточки на странице сущности используется:
background: #4B285B;
#* либо прямой <code><nowiki>{{#invoke:Сущность|get|MyEntityId}}</nowiki></code>,
border: 1.7px solid #151D28;
#* либо шаблон‑обёртка <code><nowiki>{{Сущность/карточка|MyEntityId}}</nowiki></code>.
}
# Для специализированных списков/таблиц:
</div>
#* <code>Сущность.jsonList</code> — если нужно красиво показать массив/словарь из JSON;
#* <code>Сущность.json</code> — если нужно превратить список эффектов в набор вызовов шаблона;
#* <code>GetField.get</code> — если нужно точечно вытащить одно поле;
#* <code>GetField.getTpl</code> / <code>getTplProto</code> — если нужно строить шаблоны по данным JSON автоматически.