Jump to content
Korean Random
Polyacov_Yury

Инструменты для работы с текстами в WoT

Recommended Posts

один минус мой, хотел нажать плюс, но, блин, промазал, пардон 

Не бери в голову,бывает))

  • Upvote 1
  • Downvote 2

Share this post


Link to post

Short link
Share on other sites

UPD. Поискал по картофельным скриптам функцию i18n.makeString.

1587 использований, из них 112 - идентичны тому, что мне пришлось чинить в ДинВзводах.

Такое очучение, что даже CameraNode проблему не решит, о переезде в новую папку речи не идет.

Может, не будем капризничать и/или трогать то, что есть и хоть как-то работает?)

Edited by Polyacov_Yury
  • Upvote 2

Share this post


Link to post

Short link
Share on other sites

Отстаньте уже от Реплейсера, работает из старой папки и пусть работает дальше.

Share this post


Link to post

Short link
Share on other sites

Исправил Огроменный Бажище в Краскопульте. Переведено в стадию Беты. Если ничего не изменится - выкачу вместе с остальными модами.

 

А патч таки на следующей неделе. Буду, наверное, пилить длиннопосты об изменениях в модах до их, собственно, выпуска, чтоб в день выхода патча задний план мылом не забрызгать :)
 

  • Upvote 1

Share this post


Link to post

Short link
Share on other sites

Пилю такой Краскопульт, как внезапно:

'Вот как это назвать?!'

post-8065-0-69744700-1468953235_thumb.jpgpost-8065-0-41609500-1468953249_thumb.jpg

  • Upvote 4

Share this post


Link to post

Short link
Share on other sites

Думаю. все-таки тут более подходящее место для дискуссии. Началось все тут, с перерывами на основной топик, если кому интересно, можете почитать.

Знать бы, что именно :)

P.S. Только что подумал, что благодаря JSON-у можно уйти от textList = textString.split(';') и вместо этого просто захардкодить в JSON сразу массив. Быстро и красиво :) *ушел кодить :P

Оно всегда и везде есть, чего допилить :) Если хорошо поискать.

В принципе - можно объединить наши подходы. В JSON-е сделать ремап ключ-ключ (а не ключ-текст, как у меня :) ) и по этому ремапу дёргать тексты из кастомных файлов .mo. Но опять же - излишнее усложнение работы по созданию конфига, ИМХО :)

Для простых задач, да. Есть некоторое усложнение. Но в некоторых случаях (в особенности когда дело касается переводов мода, где правится только содержимое), редактировать отдельный *.mo проще, тем более что для этого есть даже специальный софт)

А возможность в подстроку забить ключ вместо самой строки - это очень даже неплохо. Например, когда хочешь использовать какую-то картошкину строку, которая уже есть в файлах локализации.

Если ты просто короткие строки реплейсишь, то все норм. Как только дело касается чего покрупнее - вот тут начинается самое веселое. Огромные строки просто делают конфиг нечитаемым, либо приходится прилично скриллить вбок.

Если в таком раскладе просто делать ремап, а не реплейс - конфиг выглядит чисто и аккуратно, а в файлах локализации ты можешь форматировать как хочешь, или вообще софтину юзать. Опять же, если картоха решит вопрос с копированием текстов, или если просто накатить тот патч, который я им на багтрекер залил путем оверлоада i18n с добавлением кода загрузки оригинала (то, что я в загрузчиках кидал, оттуда фрагмент взять), то можно вполне спокойно с таким играться и в некоторых случаях оно будет очень даже эффективно.

А где проблема с копированием?

Мы немного о разных вещах. Ты про замену текстов, я про использование gettext для локализации своих модов, чтобы строки в конфиге не хранить. Просто ремапнул в файл локализации, как картоха делает, и все. Можно юзать строки любого размера, и конфиг при этом остается читаемым, точнее в нем вообще при изменении строки ничего не меняется.

Проблема с копированием возникает если ты пытаешься перегрузить или создать свой файл в папке текстов. То есть вынести строки из конфига в тексты.

А в версии, которая выйдет вместе с 9.15.1, я вообще полностью убрал поддержку XML, остался только JSON :)

Ну для мода, который не работает с движком игры оно и не требуется. XML хорошо работает если ты сохраняешь туда вектора или матрицы. Движок (ResMgr по сути является частью BigWorld) умеет их парсить, и тебе не нужно на эту тему напрягаться. Плюс движок еще разруливает вопрос с локацией ресурсов, и не нужно резолвить папку с патчем. Хотя по сути есть функция для этого у того же ResMgr.

*ушел кодить :P

Да я тут тоже маркеры орудий на миникарте поднять пытаюсь. Картоха с переходом на AS3 перепилила полностью миникарту. В том числе даже Scaleform класс, который ее обслуживал. Поменяли логику zIndex'a, теперь за эту штуку походу контейнер отвечает. Короче, то еще веселье. Начиная с того, что логику мода нужно наполовину вывернуть наизнанку.

Хотя в общем-то изменения положительные. Новых возможностей нормально так завезли.

  • Upvote 1

Share this post


Link to post

Short link
Share on other sites

 

 

Мы немного о разных вещах. Ты про замену текстов, я про использование gettext для локализации своих модов, чтобы строки в конфиге не хранить.
Вон оно что! А я тут, значит, сижу, понять не могу, почему я ему о маффинах, а он мне о пирожках... :heh:

Если в эту сторону понимать вопрос, то да, тогда патч gettext'a кажется вполне себе нужным. Возможность нормально хранить переводы модов в файлах .mo - очень заманчивая перспектива :)

И даже их использование как метода работы с Реплейсором начинает казаться не таким нелепым, как мне в начале обсуждения :)

 

Но даже если так - хранить свои переводы в text/lc_messages - не очень надежно. Все же в папке с конфигами - оно как-то ближе и ламповее :) (Хотя тут, похоже, дело привычки)

В любом случае - будем смотреть, как дела выгорят с фиксом i18n. Пока что оставлю так, как оно на данный момент есть, ибо меня (и, судя по всему - не только меня) все устраивает :)

 

А насчет перехода в новую папку модов - поглядим-с. По скриптам, несмотря на 1548 использований функции makeString (единственного хука на весь мод, не считая Аналитику и фиксы) - дай бог 20-я часть из них глючит.

 

 

 

Если ты просто короткие строки реплейсишь, то все норм. Как только дело касается чего покрупнее - вот тут начинается самое веселое. Огромные строки просто делают конфиг нечитаемым, либо приходится прилично скриллить вбок.
Насчет этого ко мне пока никто не обращался. Можно сделать построчный перенос конфига, если схитрить немного :)

 

Хм. А это, кстати говоря, идея. ''.join() никто не отбирал, правильно?)

 

 

 

Если в таком раскладе просто делать ремап, а не реплейс - конфиг выглядит чисто и аккуратно, а в файлах локализации ты можешь форматировать как хочешь, или вообще софтину юзать.
Тогда конфиг по факту просто туннелем является. И тут уже придется хитро-хитро покумекать. Как отличить ключ в строке от, собственно, просто строки? Можно ввести что-то вроде {key}{/key} - но это, опять же, лишнее горизонтальное танго. Посмотрим, как идея воспринята будет.

 

 

 

Проблема с копированием возникает если ты пытаешься перегрузить или создать свой файл в папке текстов. То есть вынести строки из конфига в тексты.
А вот и он. Камень преткновения во всей дискуссии. Было бы еще хитрее, если бы можно было в i18n-конфиге мода (не ремап картофельного текста, а именно мода) указать путь к папке с локализациями и оттуда читать напропалую. Юзерам потом тогда папку модов от модов чистить легче.

 

 

 

Картоха с переходом на AS3 перепилила полностью миникарту.
Весело там у вас :gg: А у меня тут, что называется, событие всплыло. Поэтому *все глядим в подпись*

Share this post


Link to post

Short link
Share on other sites

Но даже если так - хранить свои переводы в text/lc_messages - не очень надежно

Лично мое мнение - ресурсы нужно хранить в правильном месте, в специально для них отведенном. Либо допустимо рядом с модом, если это конфиг (тут речь о путях поиска конфига при старте мода), если что-то другое - туда где оно должно лежать, потому что путь к этому можно прописать в конфиге. Путь к конфигу в конфиге не пропишешь :)

как дела выгорят с фиксом i18n

В текущей итерации можно сделать фикс отдельным файлом, запилю как освобожусь. Если у тебя мод не оверлоадит i18n, то на работу игры и твоего мода это никак не скажется. Просто разрешение путей будет работать правильно.

Хм. А это, кстати говоря, идея. ''.join() никто не отбирал, правильно?)

Еще очередная доработка :)

Как отличить ключ в строке от, собственно, просто строки?

Рекурсия, она самая :) Только жаль что картоха трейлера не предусмотрела.

Было бы еще хитрее, если бы можно было в i18n-конфиге мода (не ремап картофельного текста, а именно мода) указать путь к папке с локализациями и оттуда читать напропалую. Юзерам потом тогда папку модов от модов чистить легче.

Не совсем понял. Создать свою папку локализации ничто не мешает, коллизий с картохой не будет, но и двойной уровень вложенности (требоание gettext'а) никуда не денется. А создавать папку в папке с одним файлом внутри - ну не круто. Уж проще рядом с картохиными положить (+читай выше про правильное укладывание ресурсов), только решить проблему с копированием для начала. В том то и дело, что попытка влезть в локализации тянет за собой это тупое и ненужное копирование. Потому что у программистов катохи не хватило соображаловки написать 4 простые как пареная репа строчки кода в свое время. Но судя по масштабности того, что сейчас выкатывается (речь о коде, а не о юзер-фичах), они таки начали исправляться :)

В текущей итерации можно сделать фикс отдельным файлом, запилю как освобожусь.

Как обещал. Сорц в комплекте.

i18n_patch.zip

За основу взят файл, который я запостил тут и загрузчики, которые постил тут.

Share this post


Link to post

Short link
Share on other sites

 

 

Лично мое мнение - ресурсы нужно хранить в правильном месте, в специально для них отведенном.
Полностью согласен. Вот только надо еще соглашение ввести, а где же, собственно, это отведенное место находится :) А то эти все брожения с конфигами - то рядом со скриптом конфиг клади, то в res_mods/connfigs... Вдобавок, всплывают вот эти самые "имя_файла"-конфликты. И опять же, лично мне, как мододелу, проще написать тексты для мода в JSON-конфиг, сохранить их в res_mods/configs/author_name/i18n/mod_name/lang.json и забыть, чем еще проги качать, чтобы свой .mo сделать. Хотя опять же, тут возможно влияние привычки...

 

 

 

Если у тебя мод не оверлоадит i18n
Смотря что понимать под словом "оверлоад". Если им не считать хук makeString - тогда не оверлоадит :)

 

 

 

Еще очередная доработка :)
А ты хитрый ;D

 

 

 

Рекурсия, она самая :)
А что рекурсия? Нет, понятно, что если makeString нашла в тексте ключ, надо его рекурсивно скормить себе же. Вопрос в том - как его оттуда выцепить :)

 

 

 

двойной уровень вложенности (требоание gettext'а) никуда не денется.
То есть путь text/lc_messages вшит прямо в gettext? Веселимси...
А я хотел предложить складывать .mo-шки в уже упомянутую res_mods/configs/author_name/i18n/mod_name/lang :P

 

 

 

Но судя по масштабности того, что сейчас выкатывается (речь о коде, а не о юзер-фичах), они таки начали исправляться :)
Одни compound-модели чего стоят, ага (А теперь пойми, сарказм это или нет (предыдущее указание оказалось саморекурсивным :D))

 

 

 

Как обещал. Сорц в комплекте.
Может мне на основе сего запилить Реплейсор и Краскопульт? Уж больно заманчиво избавиться от кода типа вот этого:
    def new_init(*args, **kwargs):
        old_init(*args, **kwargs)
        from gui.battle_control.battle_constants import COUNTDOWN_STATE
        from gui.Scaleform.daapi.view.battle.legacy import TimersBar
        TimersBar._STATE_TO_MESSAGE = {COUNTDOWN_STATE.WAIT: i18n.makeString('#ingame_gui:timer/waiting'),
                                       COUNTDOWN_STATE.START: i18n.makeString('#ingame_gui:timer/starting'),
                                       COUNTDOWN_STATE.STOP: i18n.makeString('#ingame_gui:timer/started')}

    old_init = game.init
    game.init = new_init

Правда, придется по факту запилить свой загрузчик i18n-модов...

  • Upvote 1

Share this post


Link to post

Short link
Share on other sites

а где же, собственно, это отведенное место находится

Картоха его считай уже ввела, разложив ресурсы по папкам. Нужно только мозги включить и по папкам пошариться - место найдется.

А то эти все брожения с конфигами - то рядом со скриптом конфиг клади, то в res_mods/connfigs...

Оба варианта имеют свои плюсы и минусы. Хотя идея вынести все конфиги в отдельную папку - очень даже неплохая. Если читаешь иногда мою темку, я там рассматривал способ переноса конфига - ремап XML секции. Как раз таки оптимальное решение и для меня, и для юзеров. Можно и конфиг разбить на мелкие как угодно, и сам по себе конфиг положить куда хочется (правда на оригинальном месте придется таки оставить файлик с редиректом).

Смотря что понимать под словом "оверлоад". Если им не считать хук makeString - тогда не оверлоадит :)

Оверлоад - это перегрузка. Когда ты кидаешь файлик в папку res_mods, который будет читаться заместо оригинала.

А ты хитрый ;D

А то :)

А что рекурсия? Нет, понятно, что если makeString нашла в тексте ключ, надо его рекурсивно скормить себе же. Вопрос в том - как его оттуда выцепить :)

Регулярка. Модуль re, в питоне есть такой :)

То есть путь text/lc_messages вшит прямо в gettext? Веселимси... А я хотел предложить складывать .mo-шки в уже упомянутую res_mods/configs/author_name/i18n/mod_name/lang :P

"text" - это типа язык, а "LC_MESSAGES" - это подкатегория типа данных, или что-то такое. Тут почитай, если с инглишем норм.

Одни compound-модели чего стоят, ага (А теперь пойми, сарказм это или нет (предыдущее указание оказалось саморекурсивным :D))

:)

Может мне на основе сего запилить Реплейсор и Краскопульт? Уж больно заманчиво избавиться от кода типа вот этого:

Если честно, не совсем понял, что ты имеешь ввиду.

Share this post


Link to post

Short link
Share on other sites

 

 

ремап XML секции.
В JSON-конфиге, ага :)
Я ж все моды при переходе на 2.0 перевел на JSON

 

 

 

Когда ты кидаешь файлик в папку res_mods, который будет читаться заместо оригинала.
Тогда ой. Сам Реплейсор-то отдельно лежит, а вот Дебаггер, который я сделал пару патчей назад и без которого я был бы, как без рук - он да, он перегружает.
Значит - будем зависеть от картофельных проггеров, что тут поделаешь -_-

 

 

 

Регулярка. Модуль re, в питоне есть такой :)
Регулярки - это и без питоновских наворотов для меня - тёмное колдунство :) (Это, правда, не мешает мне их использовать, но это не важно :heh: )

 

 

 

если с инглишем норм.
Схоронил, почитаю :)

 

 

 

Если честно, не совсем понял, что ты имеешь ввиду.
Ситэйшон следующий. Я хукнул функцию makeString уже после того, как переводы для подсказок в начале боя считались в Tuple. Поэтому, чтобы переводы для них считались из конфига и появились в игре, приходится этот tuple принудительно перечитывать после того, как функция была хукнута. А если влезть напрямую в i18n - такой проблемы не будет, потому что конфиги получат приоритет над .mo в любом всплывшем случае.

 

Есть еще другая проблема, для которой код я не привел. Это когда в сорце написано не from helpers import i18n, а from helpers.i18n import makeString. В таком случае хук функции почему-то не проходит. (см. dyn_squad_functional для примера). Таких импортов в клиенте 112 штук.

  • Upvote 1

Share this post


Link to post

Short link
Share on other sites

В JSON-конфиге, ага :) Я ж все моды при переходе на 2.0 перевел на JSON

Ну так в JSON подобное сделать тоже никто не мешает. Единственно придется мозг поднапрячь чуток.

Тогда ой. Сам Реплейсор-то отдельно лежит, а вот Дебаггер, который я сделал пару патчей назад и без которого я был бы, как без рук - он да, он перегружает. Значит - будем зависеть от картофельных проггеров, что тут поделаешь -_-

Там код открытый. Для себя впиливаешь подобное в дебаггер и вуаля. Тут вообще все проще пареной репы, тем более что сам фикс я уже запилил, там и думать особо не надо.

Регулярки - это и без питоновских наворотов для меня - тёмное колдунство :)

Ну там тоже мозг иногда напрягать приходится. Но можно решить достаточно сложные вопросы.

Ситэйшон следующий. Я хукнул функцию makeString уже после того, как переводы для подсказок в начале боя считались в Tuple. Поэтому, чтобы переводы для них считались из конфига и появились в игре, приходится этот tuple принудительно перечитывать после того, как функция была хукнута. А если влезть напрямую в i18n - такой проблемы не будет, потому что конфиги получат приоритет над .mo в любом всплывшем случае.

Ну это и ежу понятно.

Есть еще другая проблема, для которой код я не привел. Это когда в сорце написано не from helpers import i18n, а from helpers.i18n import makeString. В таком случае хук функции почему-то не проходит. (см. dyn_squad_functional для примера). Таких импортов в клиенте 112 штук.

Ну так ясен хрен. Ты почитай доки по питону, там много чего написано. По сути, хукая функцию ты заменяешь в значении переменной указатель на нее указателем на свою функцию. А если кто-то уже импортнул эту функцию, он скопировал к себе в локалспейс указатель на оригинал, и ему уже глубоко до фонаря что ты там его поменял - у него своя персональная копия. В результате ты имеешь дырку от баранки.

Отсюда простой вывод:

НУЖНО ПАТЧИТЬ ТО, ЧТО НЕ ИМПОРТИРУЕТСЯ НИКЕМ, а используется только внутри изменяемого модуля.

Например можно грамотно запилить чтобы кеш переводчиков возвращал не сам переводчик, а враппер. Переводчики никто не кэширует, точнее их кеширует кеш-класс, который ты патчишь. И они никому не нужны вне модуля, всем нужна служба - спросил-ответили.

Но опять же это ничем не поможет против тех, кто спросил и засейвил раньше чем ты хукнул - прикол тот же - у них своя персональная копия.

Так что если патчить нормально с полным покрытием - нужно грузиться раньше всех. Самый надежный способ - оверлоад файла, который тебе нужно поправить. Есть конечно вариант с хуком на импортах (в инете по этому приколу есть статейки даже), но чтобы поставить хук на импорт, нужно бутнуться до импорта, и возвращаемся туда, откуда пришли. Так что если тебе реально нужно бутнуться в самом начале - придется оверлоадить какой-то файл, который импортится в самом начале. В идеале до импорта i18n, либо дописать свой код к загрузке i18n, чтобы он выполнялся в основном ___, короче при непосредственном импорте модуля. Другого решения на питоне не может быть в принципе.

Вот тебе до кучи толковая ссылка. Надеюсь, сообразишь, что я имел ввиду пот патчем кеша.

Edited by GPCracker

Share this post


Link to post

Short link
Share on other sites

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

 

В шапке можно скачать тестовую версию Реплейсора под 9.15.1. Работоспособность на релизе не гарантирую.

 

Когда приеду (пятница) - выложу простыню, в которой распишу все изменения. Пока что могу только сказать, что старые конфиги поддерживаются в полном объеме.

  • Upvote 5

Share this post


Link to post

Short link
Share on other sites

Ага, отдых, как же...

 

Лес, горы, природа
Свет 2 часа в день, интернета нету
Баня, шашлыки, игры на свежем воздухе...
Родители, их друг с женой и моя младшая сестра.

 

Плохо выглядишь, Валера,
Что случилось? - ОТДОХНУЛ! (с)

  • Upvote 2

Share this post


Link to post

Short link
Share on other sites

Ага, отдых, как же...

 

Лес, горы, природа

Свет 2 часа в день, интернета нету

Баня, шашлыки, игры на свежем воздухе...

Родители, их друг с женой и моя младшая сестра.

 

Плохо выглядишь, Валера,

Что случилось? - ОТДОХНУЛ! (с)

+++++++++++

Share this post


Link to post

Short link
Share on other sites

Ага, отдых, как же...

 

Лес, горы, природа

Свет 2 часа в день, интернета нету

Баня, шашлыки, игры на свежем воздухе...

Родители, их друг с женой и моя младшая сестра.

 

Плохо выглядишь, Валера,

Что случилось? - ОТДОХНУЛ! (с)

не работает, и настройки тоже

Share this post


Link to post

Short link
Share on other sites

 

 

не работает, и настройки тоже
Executing: artautoaim

Этхто? (с)

Executing: hangarCalculator
Executing: hangarCalculatorButton
Executing: sniperByScroll

Тот же вопрос.

WARNING: [WARNING] (scripts/client/gui/mods/__init__.py, 69): There is problem while import gui mod ('gui.mods', 'mod_ExtraAimInfo.pyc')
ERROR: [EXCEPTION] (scripts/client/gui/mods/__init__.py, 71):
Traceback (most recent call last):
  File "scripts/client/gui/mods/__init__.py", line 64, in _findValidMODs
  File "scripts/common/Lib/importlib/__init__.py", line 37, in import_module
  File "mod_ExtraAimInfo", line 1, in <pjorion_protected>
  File "mod_ExtraAimInfo", line 1, in <pjorion_protected>
  File "mod_ExtraAimInfo", line 1, in 
	
  File "mod_ExtraAimInfo", line 17, in <module>
ImportError: No module named aims

Обновляйте читы, а потом на Реплейсор бочку катите, пожалуйста.

[OLD MODS LOADER]

Зачем? Есть же КамераНод. Вот у вас и глючит от дважды-импорта модов.

ERROR: Traceback (most recent call last):
ERROR:   File "scripts/client/gui/mods/mod_PYmodsGUI.py", line 829, in register_gui
ERROR: TypeError: addMod() got an unexpected keyword argument 'modID'

Вот за это спасибо. Надо будет отрегулировать имена переменных для кросс-совместимости (не удосужился проверить, ага)

 

P.S. Завтра будет вам патчноут. Я сегодня устал после Лаго-Наки :)

Share this post


Link to post

Short link
Share on other sites
Executing: artautoaim

Этхто? (с)

Executing: hangarCalculator
Executing: hangarCalculatorButton
Executing: sniperByScroll

Тот же вопрос.

WARNING: [WARNING] (scripts/client/gui/mods/__init__.py, 69): There is problem while import gui mod ('gui.mods', 'mod_ExtraAimInfo.pyc')
ERROR: [EXCEPTION] (scripts/client/gui/mods/__init__.py, 71):
Traceback (most recent call last):
  File "scripts/client/gui/mods/__init__.py", line 64, in _findValidMODs
  File "scripts/common/Lib/importlib/__init__.py", line 37, in import_module
  File "mod_ExtraAimInfo", line 1, in <pjorion_protected>
  File "mod_ExtraAimInfo", line 1, in <pjorion_protected>
  File "mod_ExtraAimInfo", line 1, in 
	
  File "mod_ExtraAimInfo", line 17, in <module>
ImportError: No module named aims

Обновляйте читы, а потом на Реплейсор бочку катите, пожалуйста.

[OLD MODS LOADER]

Зачем? Есть же КамераНод. Вот у вас и глючит от дважды-импорта модов.

ERROR: Traceback (most recent call last):
ERROR:   File "scripts/client/gui/mods/mod_PYmodsGUI.py", line 829, in register_gui
ERROR: TypeError: addMod() got an unexpected keyword argument 'modID'

Вот за это спасибо. Надо будет отрегулировать имена переменных для кросс-совместимости (не удосужился проверить, ага)

 

P.S. Завтра будет вам патчноут. Я сегодня устал после Лаго-Наки :)

 

new

и читов у меня нет

Edited by angelsoft

Share this post


Link to post

Short link
Share on other sites

Спасибо всем интересующимся за тестирование. Перезалил архив в шапке темы.

 

Изменения относительно неописанного бета-релиза:

  • GUI: исправлена кросс-авторная совместимость скриптов. Затенение глобальной переменной по имени 'id' - нехорошо, но зависит это не от меня, поэтому придется жить с тем, что есть.
  • CameraNode: почищен вывод в лог с учетом добавления в новом патче timestamp'ов.

P.S. Когда выкатывал "пенную" версию aka бета-релиз, забыл сказать, что отключил в моде поддержку конфигов в формате .cfg. Их все равно, как я погляжу, только я и использовал :D

 

В планах на завтра:

  • Описание релиза (пофиг, бета-не-бета, разницы никакой промежду ними окромя пары комментов в коде)
  • Нормальное сообщение в логе, если модуль GUI-настроек не установлен (а не трассировка эксепшона, которая всех только пугать будет)
  • Бета-выпуск Краскопульта (пора бы уже :З)
  • Upvote 3

Share this post


Link to post

Short link
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...