Перейти к контенту

Язык Lua. Общие вопросы программирования


Рекомендуемые сообщения

С чего начинать и где взять.

 

Установка Lua:
http://www.amk-team.ru/forum/index.php?showtopic=11584&p=629106

 

Руководство «Программирование на языке Lua», третье издание:
http://www.amk-team.ru/forum/index.php?showtopic=11584&p=905308

Изменено пользователем Kirgudu
Ссылка на комментарий

xStream,

я тоже не понимаю, почему ты предпочитаешь называть черное белым

И способ есть получше зажмуривания ;)

Ответь, пожалуйста, на вопрос:

Есть нечто, объявленное как class "XXX" (YYY). Чем является XXX? Биндером, наследником, чем-то другим?

Изменено пользователем abramcumner
Ссылка на комментарий
  Цитата
Есть нечто, объявленное как class "XXX" (YYY). Чем является XXX? Биндером, наследником, чем-то другим?

Чем-то другим - метатаблицей ;). Вообще, это напоминает спор о венгерке... Жаль что в том обилии полезностей, что выложила xStream ты усмотрел только лишь названия классов.

Ссылка на комментарий

Andrey07071977,

а точно не биндером?

Пока код xStream хоть как-то прокомментировали 2 человека, тебя среди них не было. Ты его сначала прочитай.

 

Ну и конкретно сейчас рассматривается только один скрипт перепаковки пакетов.

  Раскрывающийся текст (Показать)
Изменено пользователем abramcumner
Ссылка на комментарий

Наверное стОит обсуждать суть, а не форму, по которой (форме) у каждого свои предпочтения, и тем более дано пояснение:

  Цитата
xStream: ЗЫ Да, лакончино, скомкано и т.п. Все будет развернуто, когда доберусь до мануала. А пока тот, кто понимает, прошу вас это посмотреть, потестить. Нужен фидбек по ошибкам
- что достаточно понятно о 'форме' ...

Вот по сути далеко не все ясно.

- есть достаточно сильная зависимсость от класса 'custom_data' из хелпера, что снижает гибкость использования (ИМХО);

- есть сомнения, что в данном виде сможет быть применено/портировано в CS/SCoP ... имею ввиду не измененные параметры классов, а использование локальных копий технологических нет-пакетов;

- достачно неудобная (ИМХО) семантика вызовов, когда требуется постоянно справляться в ACDC и додумывать имена классам ...

 

Как любитель ковыряться в заинтересовавших кодах, пока не даю фидбека, т.к. на искусственных тестах и не интересно и малоинформативно, а в игру/мод встроить (не нарушая остального) требуется некоторое время (еще денек-другой). Вот тогда погоняем по полной программе.

Изменено пользователем Artos

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Ссылка на комментарий

Artos,

  Цитата
- есть достаточно сильная зависимсость от класса 'custom_data' из хелпера, что снижает гибкость использования (ИМХО);

Есть, сделана была по причине, что там, где используется (ОГСЕ и мои скрипты) кастомдата и так и так распарсивалась в таблицу. Заменить тип данных обратно на строку очень легко:

заменяем

        
{ name = 'custom_data',        type = 'cd',    default = xs_helpers.custom_data() },

на

        { name = 'custom_data',        type = 'sz',    default = '' },

Тогда для кастом даты будет обычная строка.

  Цитата
- есть сомнения, что в данном виде сможет быть применено/портировано в CS/SCoP ... имею ввиду не измененные параметры классов, а использование локальных копий технологических нет-пакетов;

Пока только ТЧ выяснялось и билд 3120. В принципе, собираюсь протестировать и на ЧН с ЗП, если и когда их установлю себе :crazy:

Мои подобные эксперименты с пакетами в ЗП никаких особых трудностей не вызывали. (Да, я слышала про трудности эти, но сама не сталкивалась)

  Цитата
- достачно неудобная (ИМХО) семантика вызовов, когда требуется постоянно справляться в ACDC и додумывать имена классам ...

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

сталкеры - xs_netpk.stalker(obj)

монстры - xs_netpk.monster(obj) (что характерно - работает со всеми монстрами, даже с разными пакетами, просто возвращает нужный, так что запариваться не надо.)

оружие - xs_netpk.weapon(obj) (сама определяет тип оружия и возвращает подходящий пакет)

рестриктор - xs_netpk.space_restrictor(obj)

левел_ченджер - xs_netpk.level_changer(obj)

аномалии - xs_netpk.anomaly(obj) (аномалии как с визуалом типа хваталки, так и обычные)

 

Все эти функции, если им подсунуть что-то "левое", вернут так называемый net_dummy. Пакет, который не делает ничего. Это сделано для избавления от разных проверок на то, правильный ли объект передали или нет. Так же все функции принимают как серверный, так и клиентский объект. Опять же, крохотное упрощение интерфейса.

Список хелперов думаю расширить. Принимаю заявки :)

 

ЗЫ Так же подумываю о специальном методе, котрый бы дампил в строку содержимое пакета, чтоб можно было узнать, какие у него свойства.

Изменено пользователем xStream

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Ссылка на комментарий

xStream,

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

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

 

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

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

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

В общем, груда потенциальных проблем, а все потому, что библиотека берет на себя не свои функции. Ей нечего делать с клиентскими объектами, она должна работать только с серверными.

 

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

Изменено пользователем malandrinus
  Полезный утиль (Показать)
Ссылка на комментарий

Согласен с точкой зрения malandrinus'а на 'net_dummy' в игре. Конечно их полезность может быть в каких-то локальных случаях/проверках, но не как общий принцип.

 

По нюансам нет-пакетов в ЗП/ЧН:

Есть подозрение, что в этих версиях ограниченно число копий объектов, выдаваемых функцией net_packet(). Т.о. в процессе игры возникают ситуации, когда по такому запросу пакета возвращается 'уже использованный' ранее объект, т.е. с не нулевыми позициями чтения/записи.

Если в читалке/писалке нет-пакетов в подобных ситуациях не контролируются позиции чтения/записи, то ... можно убежать в конец заведомо ложных (чужих) данных ...

 

Ну а по семантике вызовов, то все же стоЮ на позиции: достаточно дать на вход объект, и забота читалки/писалки идентифицировать этот объект с нужным классом, а не отдавать это на откуп модмейкеру иль сторонним скриптам. Так, хотя и чуток излишних действий требуется, но и контроль от ошибок/очепяток полный (и не особенно опытным модмейкерам поменьше заботы с именованием своих вызовов).

 

P.S. Вот по работе с клиентcкими объектами не определился ... не думаю, что это однозначно хорошо/плохо.

Привычка: всегда проверять результат вызова, поэтому если не будет возвращен 'net_dummy', то и дальнейшие операции прекращаю. Т.о. передача проверки наличия серверного объекта по клиентскому - вполне разумна и разгружает коды вызовов получения пакетов.

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

То, что это расхолаживает программиста - не совсем согласен именно в данном контексте, т.е. применительно к модмейкерам игры. Это все же в основном большинстве не программисты, а любители и помимо воспитания, все же и облегчения их "труда" восстребованы. ;-) (но это уже конечно за рамками этого топика)

Изменено пользователем Artos

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Ссылка на комментарий

Если нужен контроль, то есть метод isOk() у всех видов пакетов.

Так вы получите результат проверки, которые вы и так и так делали бы.

Либо вы забиваете, а в большинстве случаев это вполне вариант (вы только что создали объект и точно знаете, что это и что будет с ним дальше), либо получаете результат проверки (когда логика с ветвлением). При этом сработает это добро как в случае клиентский/серверный объект, так и если вообще что-то другое подсунули. Я лично предпочитаю этот метод использовать, он убирает недоразумения. При этом, несмотря на то, что "конвертирование" из клиентского в серверный предусмотрено (бывают ситуации, когда это проще), я лично сама предпочитаю передавать только серверные варианты. Что касается "пердали клиентский, а серверного нет", то как раз isOk() вернет false, а сам пакет будет net_dummy.

Операции с ним бессмысленны, а isOk() у него всегда возвращает false. Я не описала этот метод (дада, мануал), но мне кажется, он решает все сомнения и вопросы, которые были выше указаны.

  Цитата
В этом месте надо вылетать, а не делать вид, что все в порядке. Затесался к примеру вместо сталкера монстр. Очевидно ведь, что дальше делать с нетпакетами нечего.

Только что про это написала, а вот пример как раз про это в ридми (смысл в дамми появляется в ветвлениях!):

        local pk = xs_netpk.monster(obj)
        if not pk:isOk() then
            pk = xs_netpk.stalker(obj)
        end

То есть такой подход позволяет сократить код для ветвлений. И проверяем и сразу создаем, если надо.

 

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

Скажем так: предусмотрены разные уровни абстракции для разных задач.

 

ЗЫ или как вариант - сделать настройки, отключающие конвертирование и использование net_dummy, сделать это легко. И мне кажется, вполне имеет смысл.

 

Добавлено через 43 мин.:

Черт. Внимание! Есть подозрение, что работа со skeleton_flags, как тут объясняли и рекомендовали, приводит в битью пакетов и вылету.

Надо найти

{ name = 'skeleton',        type = 'skeleton' }

и закомментировать эту строку. Но возможна, скорее всего, побочка - "растянутые рельсотрупы", как в пресловутом АМК. Возможно, я неправильно организовала разбор, надо будет проверить...

Изменено пользователем xStream

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Ссылка на комментарий

xStream,

  Цитата
Если нужен контроль, то есть метод isOk() у всех видов пакетов.

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

Если кто не знает:

ASSERT(<условие>, "сообщение оь ошибке")

если <условие> не истина, то происходит вылет с выдачей сообщения. В СИ/С++ это обычно реализуется как макрос препроцессора. В Lua есть встроенный assert, но он в сталкере работает плохо, поскольку движок его часто ловит сам и вылета не делает, а просто вешает колбек, в котором он произошёл. Как уверенно вызвать вылет в сталкере - это вообще отдельный разговор, и сейчас речь не об этом. У меня своя реализация, я её активно использую.

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

 

  Цитата
        local pk = xs_netpk.monster(obj)
        if not pk:isOk() then
            pk = xs_netpk.stalker(obj)
        end

Я бы сказал, что где-то в предыдущей логике немерянная кривизна. С какой стати obj вдруг может ссылаться либо на монстра либо на сталкера? Такое может случиться в 99% случаев только если где-то накосячили: создаём не того, ищем криво, косяки в конфигах и т.д. Это надо исправлять, а не ставить затычки в подобном стиле. Если же так задумано специально, то надо "задумщику" руки обрывать.

 

 

Добавлено через 6 мин.:

Artos,

  Цитата
По нюансам нет-пакетов в ЗП/ЧН:

Есть подозрение, что в этих версиях ограниченно число копий объектов, выдаваемых функцией net_packet(). Т.о. в процессе игры возникают ситуации, когда по такому запросу пакета возвращается 'уже использованный' ранее объект, т.е. с не нулевыми позициями чтения/записи.

Нет, ограничения нет, просто не инициализируется позиция записи. Смотри здесь

 

  Полезный утиль (Показать)
Ссылка на комментарий

Саша, пример РЕАЛЬНЫЙ и используется в РЕАЛЬНОМ коде. И оно работает. Там просто составлена табличка, для выставления здоровья. Либо монстрам, либо сталкерам. И так сделано специально! Можно пользоваться IsStalker и IsMonster() и стандартно ветвить ифами-елсами. НИКТО не запрещает использовать стандартные подходы. То, что ты назвал затычкой, таковой не является. Прошу смотреть amk_offline_alife.script. Не надо вне контекста оценивать такой пример, особенно, когда заявляют что оно таки работает.

 

Сама функция isOk(), как ты верно заметил, ничего не контроллирует. Зато с ее помощью можно осуществить контроль над процессом.

Хочешь тыкать ассерты - лепи. Никто не запретит. Я придерживаюсь иного подхода: многие ошибки можно в реалтайме перехватить и обработать и они далеко не всегда фатальны. Как в вышеприведенном примере, где месиво из разных объектов. Так что я не соглашусь про барьеры и так далее. Если хочешь контроля, контроллируй, что подаешь, ассерти и все такое прочее. Сам класс-обертка содержит такой функционал, который может поломаться только если до него кто-то что-то напортачил.

 

Что касается исключений, то даже не спорю. Только такого мощного инструмента в ЛУА нет. И это явно не пойдет на пользу простому использованию (на что, в первую очередь и направлена библиотека) если такой механизм или подобный ему вводить.

Если тебе необходим ЖЕСТОЧАЙШИЙ контроль, то, как я сказала - используй непосредственно класс 100% соответствующий объекту. Никаких дамми не будет, контролируешь все сам. А хелпер на то и хелпер. Как я акцентировала - разные уровни абстракций для разных задач. Причем - не мешающие друг другу совершенно.

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Ссылка на комментарий

xStream,

  Цитата
Прошу смотреть amk_offline_alife.script. Не надо вне контекста оценивать такой пример, особенно, когда заявляют что оно таки работает.

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

Вот обсуждаемый фрагмент.

local pk = xs_netpk.monster(obj)
if not pk:isOk() then
    pk = xs_netpk.stalker(obj)
end

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

local pk = xs_netpk.monster(obj)
if not pk:isOk() then
    pk = xs_netpk.stalker(obj)
    if not pk:isOk() then
        abort("error!")
    end
end

Теперь скажи, чем хуже так?

local pk
if IsStalker(obj) then
    pk = xs_netpk.stalker(obj)
if IsMonster(obj) then
    pk = xs_netpk.monster(obj)
else
    abort("wrong object type!")
end

Ровно тот-же объём кода. Зато как минимум ясно, что здесь происходит:

Это сталкер? Получаем пакет для сталкера

Это монстр? получаем для монстра

Ни то, ни другое? Косяк, вылетаем и разбираемся, откуда взялся левый объект.

 

Вообще, идея с методом класса в стиле isOK() годится только в достаточно специальных случаях. Например, когда состояние класса зависит от внешних по отношению к системе факторов. Типичным примером являются всякие обёртки для файлового ввода/вывода. В тех-же потоках stl есть возможность генерировать исключения при ошибках, но по умолчанию отключена, и состояние потока проверяется кодом ошибки. Но там это реально обосновано, поскольку получится или нет открыть и прочитать файл реально не зависит от программиста. И решение о таком дизайне было принято далеко не с потолка, умные люди это как минимум обсудили и оставили альтернативную возможность. В данном же случае, оставляя втихую состояние объекта "не ок" - это совсем другое. Это практически всегда означает, что мы попросту прощаем ошибки программиста.

 

Поскольку я уже начинаю повторяться, то больше этот вопрос подымать не буду.

  Полезный утиль (Показать)
Ссылка на комментарий

malandrinus, посмотрел твои эвенты - красота! Но только почему ASSERT, зачем такая жестокость? Обычно в такой ситуации бросают исключение, потому на мой взгляд логичнее было бы просто ничего не сделать и как-то сообщить пользователю, что он не совсем прав. А то сразу assert делать слишком сурово.

 

В добавок мне видится ситуация, когда я хочу подписаться на эвент, если еще не подписан, и ничего не делать если подписан.

Замена ассерта на более мягкую обработку ошибки позволит тут избавиться от ветвлений типа

if not obj:is_already_subscribed(slot) then
obj:subscribe(slot)
end

К тому же с ветвлением obj:is_already_subscribed вызывается дважды.

 

Либо добавить signals_mgr:subscribe_silently() :)

Ссылка на комментарий

Саша, я тоже не хочу возвращаться, потому что будет повтор.

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

 

Добавлено через 149 мин.:

Пробный заход - описание библиотеки нет-пакетов

  Описание (Показать)
Изменено пользователем xStream

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Ссылка на комментарий

xStream,

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

Колбэки зависали, это видно по выводам в дополнительную консоль из luacap алпета. Вызов поставлен в top level event trigger – на пример в

actor_binder:on_item_use(itm)

идет следующий вызов

event(”item_use”):hangCheck():trigger({itm = itm})

, затем в методе подписчике выставляю

e:setFingerprint(”on_item_use is hanging blah blah….”)

. Сами ивенты работают прекрасно.

 

Также, по версиям файлов – так как работа над всем этим хозяйством продолжается, почему бы тебе не использовать github.com для source control. Очень удобный интерфейс, простота использования, все доступно онлайн, подсветка изменений версий кода, apps for iphone/ipad/android/etc… Люди заинтересованные в модифицировании имеют возможность сделать так называемую ”вилку” (fork) твоего кода в свою репозитори, при этом будет видно откуда была сделана вилка (кто оригинальный разраб). Ну и тд и тп ☺

 

Добавлено через 46 мин.:

malandrinus

  Цитата
У меня своя реализация, я её активно использую
- выкладывай :). Перепробовал уже с пяток разных методов, ни один не нравится, последнее на чем остановился это то с чего начал (1/uninitialized). С assert к сожалению ты прав, не всегда срабатывает, хотя наиболее изящный, на мой взгляд, способ.

П.С. Поддерживаю Monnoroch, только немного наоборот: strict_subscribe с вылетами, а subscribe, если уже подписались, просто выводит в лог сообщение (чтоб не гадать почему колбэк не срабатывает) и нечего не делает.

Изменено пользователем Andrey07071977
Ссылка на комментарий

Andrey07071977, Не надо никаких сообщений в лог. Это сажает производительность. Просто далеко не всегда подпись на эвент дважды является ошибкой в логике программы. Особенно учитывая, что мододелов куча и один может в своем моде подписать на A,B,C, а второй на B,C,D и что теперь, совмещающему всматриваться, размышлять? К тому же раскройка модов при совмещении радикально ломает всяческую инкапсуляцию.

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

Изменено пользователем Monnoroch
Ссылка на комментарий
Andrey07071977, если честно, терпеть ненавижу гитхаб. У меня есть свой СВН и меня вполне устраивает. Код не настолько сложен, чтоб заниматься бранчами и форками.

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Ссылка на комментарий

xStream, по поводу 'skeleton_flags':

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

Вот портированный вариант под xs_netpk (может сгодится):

  код (Показать)
Изменено пользователем Artos

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Ссылка на комментарий

Artos, мне просто написали, что это типа все в стейт части, так реализовала и, конечно же, оно все поломалось нахер.

Возможно, ты прав. Попробую проверить.

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Ссылка на комментарий

xStream, к сожалению тоже пока не имею информации 'как должно быть' (или хотя бы в какой части). По ранним репликам уже задавал вопрос, но пока уточнения нет. Пробовал и пробую методом тыка в state и update.

Но, и из-за малого времени проверок и ... как поймать то такой объект(?) в игре не совсем ясно - пока неяснось 'правильно иль нет'.

Сегодня попробую набрать статистики и может можно будет сделать вывод.

Изменено пользователем Artos

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Ссылка на комментарий

Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий

Комментарии могут оставлять только зарегистрированные пользователи

Создать аккаунт

Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!

Зарегистрировать новый аккаунт

Войти

Есть аккаунт? Войти.

Войти
  • Недавно просматривали   0 пользователей

    • Ни один зарегистрированный пользователь не просматривает эту страницу.
×
×
  • Создать...