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

Язык 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
 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

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

Согласен с точкой зрения 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(). Т.о. в процессе игры возникают ситуации, когда по такому запросу пакета возвращается 'уже использованный' ранее объект, т.е. с не нулевыми позициями чтения/записи.

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

 

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

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

Саша, пример РЕАЛЬНЫЙ и используется в РЕАЛЬНОМ коде. И оно работает. Там просто составлена табличка, для выставления здоровья. Либо монстрам, либо сталкерам. И так сделано специально! Можно пользоваться 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 есть возможность генерировать исключения при ошибках, но по умолчанию отключена, и состояние потока проверяется кодом ошибки. Но там это реально обосновано, поскольку получится или нет открыть и прочитать файл реально не зависит от программиста. И решение о таком дизайне было принято далеко не с потолка, умные люди это как минимум обсудили и оставили альтернативную возможность. В данном же случае, оставляя втихую состояние объекта "не ок" - это совсем другое. Это практически всегда означает, что мы попросту прощаем ошибки программиста.

 

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

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

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

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 мин.:

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

--[[---------------------------------------------------------------------
--- xs_netpk.script
--- "Правильная" работа с нет-пакетами. 

---=======================================================================---
    Интерфейс работы с классами нет-пакетов:
    0) Что это вообще такое и с чем едят?
        нет-пакет - это специальная такая фиговина, бинарный буфер, в котором лежит информация, которая описывает тот или иной объект в игре. Например, модель сталкера или монстра,
        Позиция в пространстве, поворот, текущий режим стрельбы у оружия и т.п. Просто так эта информация не доступна стандартныи средствами из скриптов.
        Все, что представлено в этом скрипте - специальные классы, которые позволяют организовать ПРОСТОЙ доступ к этим данным и их изменить в случае надобности.
        Итак...
    
    1) сначала необходимо содать объект необходимого класса, передав серверный или клиентский объект:
        а) local pk = xs_netpk.net_XXXXXX(obj)        -- указываем КОНКРЕТНЫЙ класс, как подобрать, см. ниже
        б) local pk = xs_netpk.HELPER_FUNCT(obj)    -- указываем функцию-хелпер, которая автоматически подберет нужный класс. См. тоже ниже
        
    1.1) Чтобы узнать, все ли прошло хорошо, можно вызвать pk:isOk(), он вернет true, если пакет успешно создан. false - в случае неудачи.
    
    1.2) При использовании короткоименных хелперов, появляется еще одна возможность.
            Даже если пакет не создался правильно, можно это проигнорировать, так как функция возвращает специальный пакет net_dummy,
            с ним можно производить те же операции, что и с остальными, только просто он ничего не делает. Зачем он нужен? Он полезен при условных обработках пакетов,
            пример:
            local pk = xs_netpk.monster(obj)
            if not pk:isOk() then
                pk = xs_netpk.stalker(obj)
            end
            local data = pk:get()
            data.health = health
            data.updhealth = health
            pk:set(data)
            Здесь мы НЕ проверяем, правильный ли пакет получился, когда у нас и НЕ монстр и НЕ сталкер. Потому что в результате мы получаем net_dummy
            и работаем как с обычным пакетом. Меньше кода и проверок. Но злоупотреблять этим свойством не рекомендуется. Используйте лучше isOk() в критичных
            на ошибки местах. (Код, приведенный в примере, станет понятен ниже)
            
    2) читаем данные из пакета:
        local data = pk:get()                -- в результате получаем таблицу, содержащую ВСЕ свойства объекта
        
    3) меняем нужные нам свойства:
        data.xxx = yyy                        -- простое присваивание значения нужному элементу таблицы
        
    3.1) если мы не знаем, какие свойства есть у объекта, то используем функцию:
        local description = pk:dumpDesc()    -- возвращает строку, содержащую читабельное описание пакета. Можно его, например, вывести в лог.
        
    4) после изменения, данные записываем в объект:
        pk:set(data)
        
    5) А все :) Работа сделана. Дополнительный профит: такие "пакеты" - это объекты, их можно передавать в разные функции, хранить в таблицах и т.д.
        Они "помнят", с каким игровым объектом они связаны.
        
    6) Существует специальный пакет, какой - читаем ниже и все, надеюсь, станет понятно.

---=======================================================================---
    Короткоименные хелперы-врапперы для распространенных объектов, чтобы не мучиться с подбором нужных пакетов:
        сталкеры - 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) (аномалии как с визуалом типа хваталки, так и обычные)
        + будут еще
        
---=======================================================================---
--- Если же нет функции-хелпера, а работать с объектом надо, то узнать, какой класс использовать можно очень просто:
    1) смотрим секцию объекта
    2) идем в папку со спавном и открываем ACDC (или качаем его отдельно) скрипт в редакторе
    3) листаем в конец - там есть сопоставление "секция -> пакет"
    4) смотрим пакет, меняем префикс с cse_ или se_ на net_
    Все.
    ----------------------
    Пример:
    В АСДС нашли
        physic_object         => 'cse_alife_object_physic',

    Значит, чтобы получить обертку для работы с пакетом надо сделать так:

        local pk = xs_netpk.net_alife_object_physic(obj)
        local data = pk:get()   -- прочитали пакет
        ...                        -- тут изменили данные
        pk:set(data)             -- записали пакет обратно

---=======================================================================---
--- Про специальный нет-пакет.
    Библиотека может работать с абстрактной частью пакета, которая доступна ТОЛЬКО при сохранении объекта. 
    Поэтому напрямую прочитать и записать такие данные нельзя (методами set и get). Для этого используется специальный нет_пакет net_abstract
    Хотя принцип работы отличается от работы остальных классов, но все же очень похож. Исключение составляет то, как изменять данные в пакете.
    Рассмотрю сразу на примере:
    
        local obj = alife():create("exo_outfit", pos, lv, gv)
        local pk = net_abstract(obj)
        pk:setCallback(function(data)
            data.direction = vector():set(1,1,1)
        end)
        
    Здесь мы создали объект и захотели изменить абстрактную часть. Мы указали пакету колбек, который будет вызван как только станет доступна абстрактная часть объекта.
    В колбек передается таблица с параметрами пакета, мы можем смело их менять, в примере мы наклонили объект по всем осям на 1 радиану. Изменения вступят в силу, как
    только мы выйдем из текущей скриптовой работы и управление вернется движку - он создаст объект и начнет записывать в него параметры.
    Как получить возможность менять абстрактную часть пакетов?
    
    1) этот тип объектов должен иметь класс, который представляет такой тип объектов в игре (можно назвать биндером, а можно никак не называть)
        (то есть то, что будет вызвано, когда объект появится в игре)
        Завязка из class_registrator.script:
        cs_register    (object_factory, "CStalkerOutfit",  "se_item.se_outfit",        "E_STLK",    "equ_stalker_s")

    2) обязательно сделать метод биндера STATE_Write
        Для примера с броней я сделала так:
        function se_outfit:STATE_Write(packet)
            event("se_outfit:STATE_Write_begin"):hangCheck():trigger({packet = packet, id = self.id})
            cse_alife_item_custom_outfit.STATE_Write (self, packet)
        end

    3) кинуть событие и передать туда таблицу вида {packet = packet, id = self.id}
        См. выше:
            event("se_outfit:STATE_Write_begin"):hangCheck():trigger({packet = packet, id = self.id})
        PS все можно сделать не используя песочницу xs_sandbox, но как - уже не буду расписывать. Кто знает, сам разберется.

    4) прописать в init() этого файла подписчик на это событие
        Например:
        function init()
            event("se_monster:STATE_Write_begin"):register(on_se_state_write_begin)
            event("se_outfit:STATE_Write_begin"):register(on_se_state_write_begin)
        end
    
    Выполнение этих действий ОБЯЗАТЕЛЬНО. 
    Зачем это нужно? Ну, например, можно поменять дирекшн или позишн, так как это read_only свойства объектов.
    А позишн при спавне смещается так, чтобы объект находился на ИИ сетке.
    То есть, можем спавнить всякие там лампочки, физические объкты так, чтоб они оказывались повернутыми в пространстве.
    Так же можно менять те свойства, которые, обычно, только для чтения. Например story_id, или position
    
---=======================================================================---
--- Дополнительно - классы шейпов, комплексные шейпы состоят из пачки простых
    Шейпы бывают сферические и параллелепипеды. 
    Сфера задается радиусом(число с запятой) и центром(смещение, вектор), параллелепипед - 4-мя векторами: 
    три вектора (три ребра: длина, ширина, высота; можно делать, получается, "косые" параллелепипеды) и смещение
    Пример: 
        data.shapes:addSphere(10):addSphere(5, vector():set(10,0,0)) 
    Это пример работы с левелченджером, в свойстве shapes находится complex_shape, добавляем две сферы.
    
---=======================================================================---
    Заметки:                
    - Версия нетпакетов: ТЧ(оригинал)
    - Позволяет полностью повторить работу утилиты ACDC, гарантирует правильную структуру пакета.
    - Легко расширяется, почти что копипастом, данных из скрипта ACDC
    - has NO derived - означает, что наследников у него нет, финальный класс, но это не значит, что его предки не могу существовать сами по себе

---=======================================================================---
--- TODO: 
        ~Обязательно проверить все пакеты, которые будут использовать, так как был сделан простой копипаст. 
            +Проверено оружие - безпатронное (нож), простое(дада, бинокль тут же), с устанавливаемым подстволом
            +Левелченджеры
            +Монстры
            +Сталкеры
        ~Посмотреть АСДС - при чтении у некоторых пакетов есть проверки - сделать
            +Для ТЧ сделано
        ~Расставить STATE_Write (если необходимо - создать биндеры и зарегистрировать) для необходимых объектов, 
        чтоб можно было менять абстрактную часть пакетов
            + броня
            
--- Depends on:
        xs_sandbox (optionally)
        xs_helpers
--]]---------------------------------------------------------------------

 

Ссылка на саму либу http://dl.dropbox.com/u/46539648/xs_netpk.script

--------------------

Попробовала описать весь функционал, который есть в библиотеке.

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

Добавила для желающих получить полный контроль возможность отключения дамми-пакетов и автоопределение типа объекта. Запихал хрень - сам виноват. Соответственно, перестает работать isOk()

Изменено пользователем 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 (может сгодится):

function net_ph_skeleton:__init(obj)
  super(obj)
  
  self.name  = "cse_ph_skeleton" --/ for packet dumping
  self.bases = { }
  self.props = {
    { name = 'skeleton_name',  type = 'sz',  default = '$editor' },
    { name = 'skeleton_flags', type = 'u8',  default = 0 },
    { name = 'source_id',      type = 'h16', default = -1 }
  }
  self.updprops = {
    { name = 'skeleton',       type = 'skeleton' } --/#!#
  }
end

function net_ph_skeleton:_read(ret,stpk,updpk)
  self:_read_bases(ret,stpk,updpk)
  
  if self.skip ~= skip_type.state then
    for _,prop in ipairs(self.props) do
      ret[prop.name] = this["_r_"..prop.type](stpk, prop.len)
      --/ can use ret.skeleton_flags because it is already read
      if prop.name == "skeleton_flags" and bit_and(ret.skeleton_flags, 4) == 4 then
        if self.skip ~= skip_type.update then
          self:_read_updprops(ret,stpk,updpk)
        end
      end
      --
    end
  end
  --[[ --/ или так:
  if self.skip ~= skip_type.update then
    if ret.skeleton_flags and bit_and(ret.skeleton_flags, 4) == 4 then
      self:_read_updprops(ret,stpk,updpk)
    end
  end
  --]]
end

- для записи (_write) по аналогии.

гонял в игре совсем мало, поэтому ошибок пока не заметил но и статистики нет.

 

P.S. Забыл добавить: в код писалки '_w_skeleton' вставить строку:

pk:w_u16(#val.bones)

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

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

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

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

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

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

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

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

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

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

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

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

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

Если делать в стейт части - валится стопудово.

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

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

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

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

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

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

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

Войти

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

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

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

AMK-Team.ru

×
×
  • Создать...