Monnoroch 6 Опубликовано 10 Октября 2011 (изменено) Теоретически, поскольку Lua в составе сталкера сделан в виде динамической библиотеки, то можно пересобрать эту библиотеку из исходников и добавить туда то, чего не хватает. Пытался, не прокатило, но только потому, что я не включил в него luabind. В принципе, есть вероятность что разработчики движка дописать какое-то API сами, но если нет, то в результате, после подключения luabind, должно работать. Изменено 10 Октября 2011 пользователем Monnoroch Поделиться этим сообщением Ссылка на сообщение
Monnoroch 6 Опубликовано 10 Октября 2011 То есть разработчики все же не вносили изменений в luabind? Просто не было возможности посмотреть, собирать буст с луабиндом на моем калькуляторе радости мало, и потом, винду еще ставить... но интересно же. Поделиться этим сообщением Ссылка на сообщение
Monnoroch 6 Опубликовано 13 Января 2012 malandrinus, посмотрел твои эвенты - красота! Но только почему ASSERT, зачем такая жестокость? Обычно в такой ситуации бросают исключение, потому на мой взгляд логичнее было бы просто ничего не сделать и как-то сообщить пользователю, что он не совсем прав. А то сразу assert делать слишком сурово. В добавок мне видится ситуация, когда я хочу подписаться на эвент, если еще не подписан, и ничего не делать если подписан. Замена ассерта на более мягкую обработку ошибки позволит тут избавиться от ветвлений типа if not obj:is_already_subscribed(slot) then obj:subscribe(slot) end К тому же с ветвлением obj:is_already_subscribed вызывается дважды. Либо добавить signals_mgr:subscribe_silently() Поделиться этим сообщением Ссылка на сообщение
Monnoroch 6 Опубликовано 14 Января 2012 (изменено) Andrey07071977, Не надо никаких сообщений в лог. Это сажает производительность. Просто далеко не всегда подпись на эвент дважды является ошибкой в логике программы. Особенно учитывая, что мододелов куча и один может в своем моде подписать на A,B,C, а второй на B,C,D и что теперь, совмещающему всматриваться, размышлять? К тому же раскройка модов при совмещении радикально ломает всяческую инкапсуляцию. С другой стороны получается, что теперь всегда вместо одной строки подписания придется писать три строки проверки-подписания, а всегда потому, что откуда кто знает на какие эвенты обьект уже подписан? Ну и зачем увеличивать клиентский код в три раза? Поэтому просто надо тихо return false, кому надо, тот проверит, но чаще всего это излишняя информация. Изменено 14 Января 2012 пользователем Monnoroch Поделиться этим сообщением Ссылка на сообщение
Monnoroch 6 Опубликовано 14 Января 2012 (изменено) malandrinus, Я имею в виду, что вот мы подписали, затем подписали ещё раз, затем ещё и сделали это неопределённое число раз Хранить счетчик подписываний, а не подписывать каждый раз. А пример я приводил: вот у меня класс хелпер какой-то. Мне присылают обьект и список эвентов на которые подписать. Задача - подписать на все. Ну понятно же, что не хочется каждый раз проверять - подписан ли уже, и если нет, то подписывать, хочется же сделать код прозрачней. Ну вот метод: function subscribe_all(mgr, slots) for _,v in pairs(slots) mgr:subscribe(v) end end Допустим код одной схемы вызывает: helper.subscribe_all(mgr, {s1,s2,s3}) А второй: helper.subscribe_all(mgr, {s2,s3,s4}) Вон как все красиво. Да, можно всунуть if, но как-то уже не то. Хотя вот я тут подумал - если просто в сам класс подписывателя инкапсулировать этот subscribe_all с if-ом, то будет все хорошо в плане использования. По поводу этого: когда этот ассерт будет мешать, ну так и убери его...До тех пор у меня такой функции не будет. Я думал обо всей системе, как о библиотеке, у которой есть интерфейс а реализация меня волновать не должна. И конечно пользователь сам может определить subscribe_silent с помощью того же if-а и снаружи библиотеки, но это потенциальное дублирование кода - каждый будет свою версию определять. И потом, тут проблема именно в том, что два разных человека подписывают один и тот же обьект на один и тот же эвент. Ну вот выпал мне этот ассерт - что мне делать? Ставить ту самую явную проверку, вариантов особо других нет. Я же не знаю, всегда ли так получается, что он уже подписан. Это же не мой код. И не ошибка в логике. Ты не пойми неправильно, я не пытаюсь учить ученого, просто мне показался странным подобный дизайн модуля, который потенциально может использоваться кучей народу в куче модификаций Во, кстати, я еще досмотрел и такой вопрос: почему сигнал встраивается в слот? Можно же было бы сделать как-то так: obj:subscribe(signal,slot), тогда один слот мог бы быть подпинан на множество сигналов в разное время разным кодом. Изменено 14 Января 2012 пользователем Monnoroch Поделиться этим сообщением Ссылка на сообщение
Monnoroch 6 Опубликовано 14 Января 2012 Andrey07071977, Так ведь нет же, я как раз и пытаюсь протолкнуть идею, что двойные подписки - совершенно нормальное явление. Потому и отлавливать их сомнительный профит, разве только если в конкретных случаях. Поделиться этим сообщением Ссылка на сообщение
Monnoroch 6 Опубликовано 15 Января 2012 malandrinus, Ситуация простая: некий мододел захотел на непися повесить поведение при неком скриптовом событии - например при выбросе. А выброс, так как наша система работает вокруг слот-сигнальной модели, генерирует сигнал. Ну что делает мододел - подписывает слот на сигнал. А теперь другой мододел расщедрился и хочет подписать всех сталкеров на это поведение но не знает что один уже подписан. Вот пожалуйста, двойное подписываени. Слот при этом бутет выглядеть как-то, например, так: slt = {signal = "blowout", self = obj, fun = obj.hit} и так для всех сталкеров. Ну и что, вот человек отлаживает эти моды вместе и видит: в цикле по всем сталкерам оказывается один уже подписан! Ну хорошо, и что ему делать-то? Искать где подписан и отписывать? Это копошение во внутренней реализации мода - не есть хорошо при любом раскладе. Код должен иметь как можно меньшую связность. А если разрешить двойное подписание, то все разруливается: второе подписывание элементарно игнорируется, вернее увеличивается счетчик подписываний до двух. А когда кто-то отписывает его, счетчик уменьшается до одного. А потом до нуля - и тут физически происходит отписывание. А сигнал, сколько бы раз на него слот не подписался, вызывает его, естественно только один раз, зачем ему больше? Хотя тут можно даже параметр сделать, это дело настраивающий: один или несколько. Поделиться этим сообщением Ссылка на сообщение
Monnoroch 6 Опубликовано 15 Января 2012 (изменено) malandrinus, убрать этот фрагмент и оставить более общий Предположим общий включается на первый выброс и после выключается, а частный должен работать всю игру. В добавок, в данном случае три строки не помогут: надо отписать общий случай но сохранить частный. То есть соблюдать вложенность. Я, может, пытаюсь придумать искусственный случай, но в самом деле, кто знает, как будут использовать возможность подписки? Я любитель общих решений И не любитель лезть руками в чужой код, неблагодарное это занятие, может там на четном количестве ошибок в знаке все держится? Изменено 15 Января 2012 пользователем Monnoroch Поделиться этим сообщением Ссылка на сообщение
Monnoroch 6 Опубликовано 15 Января 2012 (изменено) malandrinus, кстати об этом, а анонимная функция пойдет для решения проблемы? навроде: slt = {fun = function() return f() end} В смысле так же можно? В общем случае сработает ли такое решение: function duplicate(f) return function(...) return f(...) end end ASSERT(f ~= duplicate(f),"?") Изменено 15 Января 2012 пользователем Monnoroch Поделиться этим сообщением Ссылка на сообщение
Monnoroch 6 Опубликовано 15 Января 2012 (изменено) malandrinus, Ну да, зато у меня можно создавать сколько угодно дубликатов Добавлено через 29 мин.: Кто-нибудь может подсказать, можно ли в lua выражение: if not a then f() end заменить на a or f() И соответственно: if a then f() end заменить на a and f() Чуть более сложнее, может ли там быть statement: a and c = 1 или a or return ? Изменено 15 Января 2012 пользователем Monnoroch Поделиться этим сообщением Ссылка на сообщение
Monnoroch 6 Опубликовано 15 Января 2012 (изменено) Вот, для любителей выкладываю слот-сигнальную систему v 2.0 собственного приготовления. Она чуть более ООП, чуть менее суровая и чуть более настраиваемая. http://ifolder.ru/28140737 Ах да, делалась она на основе системы malandrinus, из оригинального кода взято обеспечение корректной работы очередей и каменты, так что не надо удивляться И да, спасибо ему за идею. И таки "a or return" не работает, по крайней мере codepad не понимает, потому там такие штуки везде накомментированы, тоже не надо удивляться... Добавлено через 18 мин.: Как-то слишком сложно. Если обобщить твой вариант для произвольной функции получится: function dublicat(f, ...) return f(...) end Но это странный вариант. Он не создает новую функцию. А моя функция принимает функцию и возвращает ее копию. А уже копию я могу приписать к тому же сигналу. Хотя тут явная проблема в том, что отписать этот слот будет затруднительно - только если закэшировать... Изменено 16 Января 2012 пользователем Monnoroch Поделиться этим сообщением Ссылка на сообщение
Monnoroch 6 Опубликовано 15 Января 2012 xStream, Да, я уже это понял Просто в D есть такая штука, что выражения типа void туда пихать можно, в результате всё expression преобразуется в statement и получаются такие вот красивые ветвления. Поделиться этим сообщением Ссылка на сообщение
Monnoroch 6 Опубликовано 16 Января 2012 Вот, добавил собственно то, что хотел: возможность множественных подключений слотов, возможность это запретить, некоторые настройки с этим связанные и вообще привел в порядок код. http://ifolder.ru/28140737 Поделиться этим сообщением Ссылка на сообщение
Monnoroch 6 Опубликовано 17 Января 2012 Вот, еще немного дополненная версия: дефолтные настройки вынесены из логики. malandrinus, теперь если в mon_utils.default_slot поставить unique = true, то получится ровно твоя система, но которую можно использовать более гибко http://ifolder.ru/28160609 Поделиться этим сообщением Ссылка на сообщение