Dennis_Chikin 3 658 Опубликовано 28 Ноября 2013 Поделиться Опубликовано 28 Ноября 2013 [q]Условия возникновения: имея кучу всяких данных в таблице, которые хотелось бы сохранить, перевожу таблицу в строку.[/q] Кстати, а зачем ? Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Ссылка на комментарий
Artos 99 Опубликовано 28 Ноября 2013 Поделиться Опубликовано 28 Ноября 2013 @Dennis_Chikin, просто у @Zander_driver'а некорректно построенна фраза. Вероятно данные в исходной таблице имели структуру вложенных таблиц. Объем данных в таблице таков, что в сумме превышает (или может) ~8 кБ , и поэтому исходная таблица по-элементно переводилась в строки... (каждая субтаблица в свою строку), чтобы запоминать по частям. "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Ссылка на комментарий
sapsan 336 Опубликовано 28 Ноября 2013 Поделиться Опубликовано 28 Ноября 2013 @Artos, а разве хранилище само не конвертирует таблицы в строки и обратно для "удобства пользования" ? P.S. Не изучал пока... Ссылка на комментарий
Dennis_Chikin 3 658 Опубликовано 28 Ноября 2013 Поделиться Опубликовано 28 Ноября 2013 По большому счету, даже выделенное хранилище совсем не нужно как таковое, со своим собственным API. Имеет смысл воткнуть его непосредственно в save_all/load_all. Все равно они вызываются исключительно при сохранениях/загрузках, но зато - всегда. А тем более не нужны постоянные бессмысленные конвертации таблиц в строки и обратно при передаче между функциями - в любом случае передается ссылка. Это просто-напросто трата памяти и времени. И даже при загрузке/сохранении получается опять же то же самое двойное/тройное преобразование, которое ведет лишь к разбуханию сохраняемых данных. Итого, всего лишь добавить к оригинальным float, bool, строка и объект еще один тип - таблица. ergo, прямо там и отслеживать размер пакета, и при необходимости начинать новый, что с таблицей - на много проще, чем с длинной строкой. P.S. А в соли мы вообще занимались полной ерундой, сохраняя мнимую "совместимость" сэйвов, когда все равно по куче других причин каждое дополнение == новая игра. И, кстати, меня слегка уже поддостало даже в той же соли выковыривать отовсюду кучу заведомо бессмысленных переменных, и еще более бессмысленных "конвертаций". В нетпакете у актора там хранить реально почти нечего. Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Ссылка на комментарий
Artos 99 Опубликовано 28 Ноября 2013 Поделиться Опубликовано 28 Ноября 2013 @sapsan, скрипт хранилища позволяет сохранять и табличные типы данных (и др.), но(!) если кол-во (кило)байт после перевода таблици в строку (и даже с компрессией) превысит 8 кБ - то скрипт не будет автоматом разрезать эту таблицу на куски, а ругнется в лог и пропустит эту таблицу. Т.о. если у модмейкера есть подозрения, что его таблица не влезет в один stor-элемент, то именно ему требуется озаботиться либо разбиением таблицы на несколько (что я бы рекомендовал), либо самому разбивать свою большую таблицу на нужные ему куски и их сохранять. "Удобства использования" все же имеют границы, за пределами которых начинаются неудобства. Вот тут и нужно вспоминать про оптимизацию... и выбирать критерии. "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Ссылка на комментарий
sapsan 336 Опубликовано 28 Ноября 2013 Поделиться Опубликовано 28 Ноября 2013 "Удобства использования" все же имеют границы, за пределами которых начинаются неудобства.Тоесть обычное преобразование таблицы в строку и обратно выходит за границы удобств ? Ссылка на комментарий
Dennis_Chikin 3 658 Опубликовано 28 Ноября 2013 Поделиться Опубликовано 28 Ноября 2013 sapsan, не нужно оно. По крайней мер в соли - точно. Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Ссылка на комментарий
Artos 99 Опубликовано 28 Ноября 2013 Поделиться Опубликовано 28 Ноября 2013 (изменено) @Dennis_Chikin, что-то ты брякнул, что и мне сложновато понять... Во-первых, скрипт хранилища как раз и выполняет все "непосредственно в save_all/load_all". Во-вторых, полностью согласен, что в пакете актора по сути то хранить можно "копейки", но как раз в рассматриваемом случае потребно целую "кучу" где-то, но сохранять. @sapsan, тебе же уже не раз написано, что исходная таблица в данном случае содержит такое кол-во данных, что при переводе в строку (сериализации) кол-во байт строки превышает 8 кБ. А это уже не просто "удобства", а ограничение движка игры! Т.о. если хочешь использовать "удобное хранение" - потрудись не превышать размер строки в 8 кБ или же сохраняй/дроби сам как тебе вздумается. Если же все твои данные таковы, что ни при каких условиях каждая "порция" для сохранения не превысит ограничения по пакету - пользуйся сколь угодно преобразованиями. Изменено 28 Ноября 2013 пользователем Artos "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Ссылка на комментарий
Dennis_Chikin 3 658 Опубликовано 28 Ноября 2013 Поделиться Опубликовано 28 Ноября 2013 простейшая модификация оригинала: function pstor_save_tbl( t, pk ) pk:w_u8( pstor_table ) local p for k, v in pairs( t ) do if type( k ) == "number" then pk:w_u8( pstor_number ); pk:w_float( k ) else pk:w_u8( pstor_string ); pk:w_stringZ( k ) end if v == true then pk:w_u8( pstor_true ) elseif v == false then pk:w_u8( pstor_false ) else p = type( v ) if p == "number" then pk:w_u8( pstor_number ); pk:w_float( v ) elseif p == "string" then pk:w_u8( pstor_string ); pk:w_stringZ( v ) elseif p == "userdata" then pk:w_u8( pstor_custom ) if v.classname == k then pk:w_stringZ( "" ) else pk:w_stringZ( v.classname ) end v:save( pk ) elseif p == "table" then pstor_save_tbl( v, pk ) else abort( "pstor_save_all, not registered type: %s, k: %s", p, k ) end end end pk:w_u8( pstor_end_t ) end function pstor_save_all( npc, pk ) local pstor = db.storage[npc:id()].pstor if not pstor then pstor = {} db.storage[npc:id()].pstor = pstor end local n = 0 for k, v in pairs( pstor ) do n = n + 1 end pk:w_u32( n ) local p for k, v in pairs( pstor ) do pk:w_stringZ( k ) if v == true then pk:w_u8( pstor_true ) elseif v == false then pk:w_u8( pstor_false ) else p = type( v ) if p == "number" then pk:w_u8( pstor_number ); pk:w_float( v ) elseif p == "string" then pk:w_u8( pstor_string ); pk:w_stringZ( v ) elseif p == "userdata" then pk:w_u8( pstor_custom ) if v.classname == k then pk:w_stringZ( "" ) else pk:w_stringZ( v.classname ) end v:save( pk ) elseif p == "table" then pstor_save_tbl( v, pk ) else abort( "pstor_save_all, not registered type: %s, k: %s", t, k, _util.to_str( npc ) ) end end end end Загрузка - аналогично. Дальнейшая модификация путем скрещивания с "универсальным хранилищем" для толстых таблиц - очевидна. Осталось придумать, для чего бы могли понадобиться эти толстые таблицы. 1 Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Ссылка на комментарий
sapsan 336 Опубликовано 28 Ноября 2013 Поделиться Опубликовано 28 Ноября 2013 (изменено) @Dennis_Chikin, это проще, чем писать менеджер сохранения таблицы в виде простых типов. тебе же уже не раз написано, что исходная таблица в данном случае содержит такое кол-во данных, что при переводе в строку (сериализации) кол-во байт строки превышает 8 кБ Где это написано ? От автора вопроса уточнения не было. И его сообщение я трактую однозначно - он сохраняет много преобразованных в строки таблиц, а не одну огромную таблицу с подтаблицами. Было лишь твоё предположение о последнем варианте. И если оно верно - это проблема автора вопроса, а не баг в хранилище. Если же не верно - вероятно он замучил хранилище до выявления бага. Почему бы не подождать уточнения от него самого, а не тыкать друг в друга авторитетными гипотезами ? простейшая модификация оригинала Оставляю вас далее строить свои домысли и погадалки... И ушел он в обнимку со своим домыслом... Изменено 28 Ноября 2013 пользователем sapsan 1 1 Ссылка на комментарий
Artos 99 Опубликовано 28 Ноября 2013 Поделиться Опубликовано 28 Ноября 2013 (изменено) @Dennis_Chikin, ты "тихо сам с собою" иль как? Исходное сообщение Zander_driver'а о том, что при сохранении большой таблицы у него со скриптом se_stor.script возникает ошибка переполнения. Способы конвертирования таблицы в строку (иль иной тип данных) давным давно известны, применяются и в данном случае не рассматриваются (пока). Ты спросил: "Зачем переводить в строку", на что дан ответ: "Чтобы разрезать таблицу на части, т.к. строка всей таблицы превышает допустимый размер!". Ну и что же ты с чем собрался скрещивать, предлагая очередной (с ошибками и сильно ограниченный) вариант сериализации "аля xStream" при тех же самых 8-ми кило на пакет?! Где это написано ? Автор исходного сообщения пишет об одной таблице, мною (в ответ на заданный вопрос о переводе в строки) дано пояснение (единственно возможное в данной ситуации)... Оставляю вас далее строить свои домысли и погадалки... Вот только что и кому вы пытаетесь показать иль объяснить? P.S. Вот только троллить, переходя на личности, не стОит... Теперь просто вас начну игнорировать. Изменено 28 Ноября 2013 пользователем Artos "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Ссылка на комментарий
*Shoker* 322 Опубликовано 28 Ноября 2013 Поделиться Опубликовано 28 Ноября 2013 (изменено) В наличии есть матрица углов поворота объекта и его позиция. Могу из неё также получить углы Эйлера.Никто случаем не может показать готовую функцию (можно даже не на Lua, лишь бы понятная была) с помощью которой зная эти данные можно получить направляющий вектор?(в смысле вектор, который при сложении с позицией показывает на точку в метре от объекта, на которую он смотрит - грубо говоря то что возвращает direction() у объекта или device().cam_dir у камеры) Необходимо получить дирекцию кости, но я могу только углы Эйлера\матрицу поворота из неё вытащить. А как через них получить направляющий вектор (он кстати вроде по другому называется) я честно говоря не знаю. UPD: Вроде выкрутился вот такой шнягой: local ph_shell = self.object:get_physics_shell() local ph_element = ph_shell:get_element_by_bone_name("link") function extract_direction(ph_element) local m = ph_element:global_transform() local p,b,h = extract_euler_xzy(m) return vector():setHP(h, p) end extract_euler_xzy - http://pastebin.com/6ijsymZ4 Изменено 28 Ноября 2013 пользователем *Shoker* 1 Можно просто Shoker, форум АМК съел моё старое имя и не хочет отдавать о_О Мастер аномалий на свою заднюю точку. Ссылка на комментарий
Zander_driver 10 333 Опубликовано 29 Ноября 2013 Поделиться Опубликовано 29 Ноября 2013 Неужели я неясно выразился. Нет же, Артос, никогда там не было одной большой таблицы, тем более размером более 8кб. были тысячи таблиц примерно по 200 байт. Чтобы не перекладывать на se_stor то с чем я и сам справлюсь, упаковал их в строки самостоятельно. и стал записывать. ни одна из строк не превышала 130 байт, просто их были тысячи. и при размере пакета 8000 байт возникало переполнение. сделал запас в 200 байт - проблема исчезла. лог, если так уж необходим, могу воспроизвести, вернув обратно на 8000. Полагаю ошибка где то в алгоритме "когда надо переключаться на следующий объект". т.к. повторюсь, ни один из элементов которые я скармливал в se_stor, никогда не был такого размера чтобы в одиночку вызвать переполнение. Ну и по поводу сохранения тысяч элементов... я думаю из того вопроса который был в личке, вы поймете что я сохраняю. Отсюда уже несложно сообразить зачем. 1 Мод, где не бывает одинаковых путей - Судьба Зоны. (Лучшее, что у меня получилось на X-Ray) На базе модифицированного движка OGSR Engine. Бывший мододел на X-Ray / Начинающий игродел на Unreal Engine. Программист. AMD Ryzen 9 7950X (16 ядер, 32 потока, 5.75 ГГц); RTX 3080; 128 ГБ DDR5; Arctic Liquid Freezer II-420; 3 ТБ SSD PCIe 4.0; 4ТБ HDD. Ссылка на комментарий
Artos 99 Опубликовано 29 Ноября 2013 Поделиться Опубликовано 29 Ноября 2013 (изменено) Неужели я неясно выразился. Как можно видеть из возникших вопросов - недостаточно ясно..., а точнее для любителей шарад или гаданий. @Zander_driver, какова цель твоего исходного поста #5414? Сообщить о возможной ситуации, когда в скрипте (неизвестном для многих) у тебя возникает ошибка? А кому, кроме тебя иль меня это интересно? Да и для меня, без технической информации, это просто пустой оффтопик, а тебе ".. было лень поэтому просто уменьшил предельный размер пакета..". Даже на мой ответ и фразу о необходимости хотя бы лога(!), ты продолжаешь пустые предполагалки и "если так уж необходим, могу воспроизвести,...". Судя по твоим описаниям, действительно ошибка может происходить из-за некорректного определения границы объема пакета, однако без конкретных строк лога и/или твоего кода не вижу возможности найти причину и исправить. Вслепую снижать границу для мнимого исчезновения вероятности ошибки(?) - уже писал, что не считаю это правильным вариантом (тем более на моих кодах ошибка не проявляется). Ну а по оптимизации, не стОит из меня делать Кашпировского... Я все же не экстрасенс и не любитель гадать на кофейной гуще, чтобы по куцым и завуалированным фразам в личке строить догадки и тем более соображать зачем это кому-то. Ну а пока мне все же непонятны такие "тысячи записей из строк" - остаюсь прежнего мнения о не оптимальности принятых для сохранения данных. Что-то не верится, что эти несколько тысяч записей возникают в следствии игры и именно эксклюзивны, а не воспроизводимы вновь. (ну да это как говорится: "хозяин барин") Полагаю ошибка где то в алгоритме "когда надо переключаться на следующий объект". Хм, судя по описаниям, ошибка НЕ в алгоритме, а в конкретном числе для границы пакета. Если это так, то я бы предпочел перепроверить и определить причину, чтобы установить безопасную границу, а не гадать в слепую... P.S. Кстати, ты так и не ответил на заданный вопрос: [q]Условия возникновения: имея кучу всяких данных в таблице, которые хотелось бы сохранить, перевожу таблицу в строку.[/q] Кстати, а зачем ? ... и, просто предположение, не из-за "ручного" ли перевода возникает проблема? Изменено 29 Ноября 2013 пользователем Artos 1 "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Ссылка на комментарий
Dennis_Chikin 3 658 Опубликовано 29 Ноября 2013 Поделиться Опубликовано 29 Ноября 2013 (изменено) Artos,Про ошибки хочу подробностей. Ну, кроме как про выкинуть остатки "псевдосовместимости" в виде подсчета количества переменных, которые низачем не нужны, но знатно тормозят.По поводу ограниченности - это еще всякую лабуду типа векторов сохранять ? Не, не нужна. Их все равно надо чуть не при каждой операции руками копировать, и при этом черт его знает, что у них там внутри.А модифицируется это в дальнейшем, если бы оно было зачем-то надо, просто тупо проверкой размера нетпакета после записи очередной переменной, и если больше максимально разрешенного размера - создаем другое хранилище, и продолжаем писать уже в него.Теперь возвращаемся к преобразованию таблиц в строки:С учетом того, что в луа для этого нет адекватных средств - оверхэд получается просто чудовищный. Сами данные при этом также разбухают (ага, тэги, да и просто num в strZ).Далее, получив строку, не лезущую в остаток пакета, я так понимаю, предлагается применить к ней string.sub(), в обрамлении некоторой логики ? Опять же, оверхэд. В то время, как при поэлементной записи делить ничего не надо - просто продолжать писать в другой. И так же и читать.Да, записаны данные получаются "рыхло". Сэйв увеличивается в размере. Но поскольку это происходит уже не в скрипте - это будет всяко быстрее.Zander_driver, а добавить контроль размера пакета после записи каждой строки, и писать его в лог - не ? Естественно, что при записи в него 8 кил - переполнится. Изменено 30 Ноября 2013 пользователем ColR_iT Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Ссылка на комментарий
Artos 99 Опубликовано 29 Ноября 2013 Поделиться Опубликовано 29 Ноября 2013 Про ошибки хочу подробностей. Хотеть не вредно, но лучше их попросить... После того как посмотрел топик по разработкам в солянке, стал понятен твой интерес к этой теме. Ошибки бывают (и у тебя присутствуют) различного типа: 1. Ошибка применения необъявленной переменной: в строке else abort( "pstor_save_all, not registered type: %s, k: %s", t, k, _util.to_str( npc ) ) используется необъявленная переменная (t вместо p), что приведет к потере информации в функции прерывания игры о причине предыдущей ошибки. 2. Ошибочно предлагать "простейшую модификацию оригинала" для использования типа данных "userdata" при том, что не оговоривается обязательность наличия в таких данных неких v.classname и v:save, коих в оригинальных объектах в игре практически не встречается или имеются только в классах типа биндеров. Подобное без ограничений применения просто напросто будет вызывать ошибки при попытках модмейкеров сохранить, например, вектор позиции иль гейм-таймер (CTime) иль подобное..., а с ограничением - см.фразу о "сильно ограничивает". 3. Можно и далее продолжить разбор "простейшей модификации", но не вижу пока надобности, т.к. имеются более продвинутые варианты записи различных данных в сэйв(ы). Если есть желание сравнить и порассуждать - нет проблем, но тогда тебе придется ознакомиться с уже имеющимися вариантами (хотя бы с тем, о котором речь в исходном посте). А модифицируется это в дальнейшем, если бы оно было зачем-то надо, просто тупо проверкой размера нетпакета после записи очередной переменной, и если больше максимально разрешенного размера - создаем другое хранилище, и продолжаем писать уже в него. Именно "тупо"! К твоему сведению если ты в нет-пакет что-то записал, то что-то проверять после записи уже поздно будет... т.к. если переполнение, то придется уже "выкидывать" этот нет-пакет и все перезаписывать заново. Именно на этом этапе и пишет про ошибку Zander_driver, и именно тут имеется некая неопределенность: то ли выбранная граница максимума для записи велика, то ли имеется ошибка перевода в строки и их запись в сэйв... По "преобразованию таблиц в строки" нам пока рано (иль поздно) говорить. 1. Моя позиция проста: "Любая таблица для записи в сэйв НЕ должна превышать 8 кБ! Если превышает - модмейкер должен заранее позаботиться о разделении на приемлемые части." Именно на этом основан алгоритм скрипта общего хранилища, т.е. любые строки/таблицы более 8 кБ просто игнорируются с сообщением об этом в лог. Если тебе или кому-то хочется на лету делить автоматом строки/таблицы и распределять по разным объектам с последующими слияниями - нет проблем, пишите свои варианты (с string.sub() иль иным). 2. Варианты сериализации и даже с компрессией давно уже есть и никакого чудовищного оверхеда не наблюдается. Если организовать данные и писать их в сэйв с умом(!) то даже при записи чисел строками можно выиграть в объемах! Но все конечно зависит от контента и огульно все сваливать в кучу - ошибочно! Кстати, это еще один тип ошибки (не оптимальность) в твоем варианте записи pstor'ов. Но поскольку это происходит уже не в скрипте - это будет всяко быстрее. Позвольте поинтересоваться: "не в скрипте" - это где? где это будет быстрее и по какой такой причине? "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Ссылка на комментарий
Zander_driver 10 333 Опубликовано 29 Ноября 2013 Поделиться Опубликовано 29 Ноября 2013 и, просто предположение, не из-за "ручного" ли перевода возникает проблема? Помилуйте. Тот пост я писал утром, собираясь на работу. Возпроизводить тот лог у меня банально не было времени. и, по вашему преположению. Я для полноты картины выводил в лог все те строки, которые отправлялись в se_stor на сохранение. ни одна из них не превышала 130 символов. Сейчас воспроизведу тот вылет... Мод, где не бывает одинаковых путей - Судьба Зоны. (Лучшее, что у меня получилось на X-Ray) На базе модифицированного движка OGSR Engine. Бывший мододел на X-Ray / Начинающий игродел на Unreal Engine. Программист. AMD Ryzen 9 7950X (16 ядер, 32 потока, 5.75 ГГц); RTX 3080; 128 ГБ DDR5; Arctic Liquid Freezer II-420; 3 ТБ SSD PCIe 4.0; 4ТБ HDD. Ссылка на комментарий
Artos 99 Опубликовано 29 Ноября 2013 Поделиться Опубликовано 29 Ноября 2013 @Zander_driver, никто и не гонит и не требует сразу же реагировать на реплики, как и вообще писать посты без необходимой информации. Нужны логИ, по строкам которых можно было бы понять причину сбоя/ошибки. Если по какой-то причине сбой именно из-за "переполнения", то нужен лог записи, в котором были бы указаны объемы записи в каждый элемент и соответственно строки лога чтения из этих элементов из сэйва. В скрипте вывод этой информации предусмотрен. Так же, нет подозрений на превышение какой-то отдельной строки более чем 8 кБ, а есть подозрение, что или сама строка после "ручного" перевода своей таблички оказалась "странной" или еще какой-то неясный сбой при сохранении цепочки строк (пересечение имен, недопустимые символы в именах, ...) В общем не гадать нужно, а анализировать информацию (которая отсутствует)! "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Ссылка на комментарий
Zander_driver 10 333 Опубликовано 30 Ноября 2013 Поделиться Опубликовано 30 Ноября 2013 (изменено) Можно ли каким то образом сменить комьюнити смарт-террейна в игре? (ТЧ) Кстати, пытаясь выяснить этот вопрос, попытался получить список серверных объектов по clsid.smartterrain. С удивлением обнаружил что таких объектов на сервере нет. Хотя в class_registrator.script регистрируется именно такой. И смарт-террейны в игре есть. сам скрипт рабочий, когда с его помощью получаю серверные объекты сталкеров, мобов, аномалий, оружия и прочего - все работает. И возвращает все что требуется. Изменено 30 Ноября 2013 пользователем Zander_driver Мод, где не бывает одинаковых путей - Судьба Зоны. (Лучшее, что у меня получилось на X-Ray) На базе модифицированного движка OGSR Engine. Бывший мододел на X-Ray / Начинающий игродел на Unreal Engine. Программист. AMD Ryzen 9 7950X (16 ядер, 32 потока, 5.75 ГГц); RTX 3080; 128 ГБ DDR5; Arctic Liquid Freezer II-420; 3 ТБ SSD PCIe 4.0; 4ТБ HDD. Ссылка на комментарий
Artos 99 Опубликовано 30 Ноября 2013 Поделиться Опубликовано 30 Ноября 2013 (изменено) @Zander_driver, все же по-аккуратнее и по-понятнее стОит формулировать вопросы/посты. 1. Нет в оригинальных играх серии Сталкера объектов с сидами 'smartterrain', а есть для 'smart_terrain' (clsid.smart_terrain). Этот же сид регистрируется и в class_registrator.script. 2. Как можно сменить то, чего нет? Нет для смарт-террейнов такого понятия 'комьюнити'. Имеется возможность задать параметр 'accepted_communities' - табличку в которой перечислены допустимые/разрешенные для гулага группировки. Можно было бы net-пакетами менять в кастомдате значения для этого параметра, но... пока нет стабильных вариантов для этого класса. Но не сложно в игре в нужное время менять эту табличку (accepted_communities) по своему разумению, естественно дополнительно написав свои изменяющие функции. Изменено 30 Ноября 2013 пользователем Artos "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Ссылка на комментарий
Рекомендуемые сообщения
Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий
Комментарии могут оставлять только зарегистрированные пользователи
Создать аккаунт
Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!
Зарегистрировать новый аккаунтВойти
Есть аккаунт? Войти.
Войти