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

Язык 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, ну тогда сменим ракурс нашего обсуждения.

Причиной нашего взаимного непонимания, по крайней мере с моей стороны, послужило то, что ты выложила свой вариант (см. #159) именно в связке с песочницей by Andrey07071977.

Дополнтельно, довольно вольное определение 'песочница' с твоей стороны, также послужило причиной разговора о разных вещах.

Все же общеупотребимое понятие:

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

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

 

Хорошо, давай говорить об именно концепте, а не уже практическом воплощении в играбельный вариант для 'кучерявого' мода ... ;-)

 

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

В данной реализации невозможно выполнять события (driven-events), которые являются 'дочерними' (ведомыми) по отношению к основному (event), т.е. генерируются в цикле исполнения основного события.

Если в цикле обработки события (event_parent) в подписанных на него модулях произойдет генерация другого события (event_driven) - то это новое сгенерированное событие (event_driven) и его цикл обрабоки приведет к тому, что в конце отработки этого нового сбытия (вложенного по времени в основное событие!) будет вызвана проверка наличия 'зависших' событий (#events_in_process>0) и еще не завершенное (не закончен цикл) родительское событие (event_parent) будет воспринято как зависшее(!). Т.о. произойдет вызов завершения приложения по якобы фатальной ошибке зависшего треда.

Примером может являться например такая ситуация:

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

 

Это ограничение несложно обойти, введя в алгоритм sandbox'а возможность зависимым событиям выставлять некий флаг/признак, по которому игнорировать в 'зависших' незавершенные (а не зависшие) события.

ИМХО, такое увеличение сложности все же именно повышает безопасность использования "песочницы" сторонними модулями.

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

 

P.S. Если будешь дорабатывать в сторону усложнения - хотелось бы увидеть этот доработанный вариант, дабы сравнить решение со своим.

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

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

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

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

 

И что значит - в сторону усложнения? :) Я наоборот всегда стремлюсь к упрощению интерфейсов

 

ЗЫ Ах да, обработчик зависших событий сейчас не работает из-за того, что массив неиндексированный, а ассоциативный... Я это у себя пофиксила. Решу проблему с "матрешкой" ивентов, тогда выложу решение.

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

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

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

Имел ввиду под усложнением не усложнение интерфейсов, а усложнение функционала, хотя конечно же последнее нередко приводит к первому.

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

 

У меня как раз обработчик зависших событий работает (хотя код аалогичен твоему). Именно им и обнаружил ограничение по вложенности при адаптации под свои нужды ... Ведь не зря же предлагал заменить '#events_in_process>0' => 'next(events_in_process)' ! ;-)

 

И, если все же интересно, еще некоторый нюанс применения:

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

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

Это к тому, что простота в одном месте приводит к усложнению в другом(других) ... хотя в данном случае суммарный выигрыш по простоте все же за данным вариантом!

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

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

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

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

 

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

 

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

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

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

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

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

 

В дополнение кину еще одну косточку для размышлений (не по концепту, а для ... все же тему читают и вдумчивые):

ИМХО, может быть (но не в данном концепте, а в его расширенной реализации) стОит предусмотреть четыре типа поведения на различных отрезках игры:

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

- 'штатный' режим игры;

- создание сэйва;

- завершение игры.

Все же и транспортные связи и реакция на события у одних и тех же модулей/функций в этих режимах могут сильно отличаться: вплоть до полного игнорирования события ... Регистрация модулей и подписка только в самом начале игры (при инициализации модулей) все же довольно существенное ограничение (ИМХО).

 

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

Но не выстреливать, а просто создавать, заполнять и передавать - получится унифицированность.

Жду (но НЕ тороплю!) доработанного варианта - сравним. Не предлагаю - дабы не навешивать шоры ... :-)

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

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

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

Ничто не мешает сделать event("xxxx"):register(yyyy) после старта игры.

Как я обращала внимание - это так называемые "статические" связи, те, что в init()

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

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

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

А вот я наоборот ... залез пока в дебри (адаптируя и расширяя функционал данного сэндбокса) и пока не до семантики. ;-)

Пока все отлично и работает и пр. ... Ощутимомго ыыигрыша/проигрыша по производительности (пока) нет, но в конечном итоге код получается более законченным, логичным и функциональным.

Расширил его на таймеры и, все время терзает вопрос: Судя по несколько раннеей твоей реплике, по таймерам у тебя тоже некий задел/набросок имеется(?). Но, без расширения синтаксиса/семантики интерфейса (хотя бы по аргументам вызова/обращения к объектам класса) тут не обойтись. Ведь требуется и время задавать и прочее ... В этом направлении (применительно к таймерам) ты подразумевала этот же сэндбокс или ...?

(вынужден отлучиться до вечера)

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

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

http://dl.dropbox.com/u/46539648/xs_sandbox.rar - смотреть мануал, в секции для "продвинутых", о том, как организовать проверки на зависание.

 

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

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

 

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

Мне кажется, ты просто пошел не тем путем. В терминах игры и ООП, то, о чем ты говорил - так называемые стейты (загрузка, игра, сейв, ...).

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

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

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

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

xStream, эх, не успел посмотреть ... т.к. по ссылке лежит прежняя версия (1.0.2) в которой только в описании упоминается про hangCheck (в кодах ни разу).

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

По таймерам чуть позже поясню. Все же это (в моем понимании и в твоих терминах) аналогичные события (events), хотя и зависимые от коллбэка апдейта актора, но "выстреливающие" в строго заданное время. Т.е. все же событие, которое по исполнению кодов зависимо от породившего основное, но автономно по своей сути. Пока, срастив эти два функционала (класс событий и функции таймеров) получилось очень (ИМХО) неплохо (и функционально и логично и надежно). Причешу коды - выложу то, что вышло ...

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

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

Ссылка на комментарий
в которой только в описании упоминается про hangCheck (в кодах ни разу).

В кодах каких? Оно использоваться должно там, где кидается ивент, а не где отрабатывается. Пример я в описании привела.

 

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

http://dl.dropbox.com/u/46539648/xs_timers.script - пример таймеров, как обещала.

НЕОПТИМИЗИРОВАНО! Все повешено на актора.

Кроме того, не уверена в том, как работают замыкания в ЛУА, так что function timer:run(time_seconds) - под вопросом, но суть такая.

 

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

 

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

Пример использования:

local kill_timer = timer()
kill_timer:bind(kill_object, function(object) object:kill(object) end)
kill_timer:run(10)

Через десять секунд после запуска таймера, помрет непись kill_object.

 

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

Ура, замыкания рулят - http://www.lua.org/pil/6.1.html

Значит код рабочий.

 

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

Artos, сделала отрегистрацию, как ты просил. В любой момент. Надо помнить - передавать надо ТУ ЖЕ самую функцию, которая передавалась на регистрацию.

И применила этот подход в тестовых таймерах.

 

Все, что изменяла, засунула в архив с песочницей

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

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

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

Или я пере...курил или пора с кодингом завязывать ... :-)

xStream: Оно использоваться должно там, где кидается ивент, а не где отрабатывается. Пример я в описании привела
Хм, это то ясно и из примера и по сути, но:

Читаем в readme:

NOTE! Включение проверки на зависание биндера производится методом event:hangCheck() ДО "выстреливания" ивента....

Пример: event("actor_spawn"):hangCheck():trigger({data = data})

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

Я так понимаю, что в классе 'event' должно присутсятвокать как минимум типа этого:

function event:hangCheck()
  self.__dbg_check = true --/ флаг необходимости проверки зависших тредов
  return self --/>
end

и дополнительно в function trigger(evt), перед собственно циклом проверки массива events_in_process - начинать проверку только при наличии установленного флага разрешения этой проверки, т.е. типа:

-- event callbacks can trigger another events but they must have different type
local function trigger(evt)
  ...
  -- hang debug
  if evt.__dbg_check and next(events_in_process) then
  ...

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

Да и замена #events_in_process => next(events_in_process) позволит все же проверять неиндексный массив.

 

К сожалению не могу скачать и посмотреть пример для таймеров, т.к. хост Dropbox'а выдает 404-ю ошибку ... Вероятно расширение 'script' у отдаваемого файла не в числе валидных для трансфера по запросам. Просьба, перезалей в виде архива.

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

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

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

Ты какую-то глупость пишешь.

hangChek - есть у объекта класса event всегда. Ты уверен, что смотришь последнюю версию?

Качай архив целиком! Я же написала, что все-все запихала в архив. http://dl.dropbox.com/u/46539648/xs_sandbox.rar. 404 - файл просто удален. Ибо если есть в архиве, то и не нужен отдельно

 

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

А что касается next, то я не знаю, что ты смотришь. Там все давно переделано на индексированный массив...

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

 

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

Предлагаю переместиться в аську, если процесс установления абсолютной истины слишком медленен :)

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

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

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

xStream, предлагаю все же несколько сдержаннее быть в словах ...

Ведь написал же не зря:

т.к. по ссылке лежит прежняя версия (1.0.2) в которой только в описании упоминается про hangCheck
, т.к. по ссылке из поста #213 перекачивал не менее 4-х раз (напрямую и качалками), грехов за прокси провайдера не замечал ... И сам недоумевал по поводу странности с hangChek - поэтому и переспроси и дал обоснование.

В архиве от "вчера" описание лехало от 26-го, а xs_sandbox.script от 21-го.

Сейчас перекачал, в архиве и обновленные версии скриптов (1.0.3) и вижу срипт по таймерам. Спасибо, смотрю ...

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

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

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

Я сдержана и спокойна как удав. Просто я же тоже не просто так писала, что в архив все положила :)

А ты мне про 404. Из чего я делаю вывод, что смотришь ты не то. На фоне чего твои замечания теряют силу.

 

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

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

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

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

Про 404 ошибку писал в контесте ссылки именно на скрипт наработки по таймерам, о чем и про расширение скачиваемого файла упомянул.

(ну да этот вопрос уже проехели ... просто я менее спокоен порою чем удав ;-) )

 

А в чем причина тяготения к варианту:

  if #events_in_process>0 then
  ...
  end
  ...
  events_in_process[#events_in_process+1] = evt
  ...
  events_in_process[#events_in_process] = nil

перед таким:

  if next(events_in_process) then
  ...
  end
  ...
  events_in_process[callback_name] = evt
  ...
  events_in_process[callback_name] = nil

Просто более привычно или имеет более практичный смысл?

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

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

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

А очень простая: при моем подходе порядок сохраняется, а при использовании next ЛУА не гарантирует, что элементы достаются по порядку. Недостаток у next такой же, как у pairs.

А если я хочу развернуть стек вложенных ивентов, в результате которых произошло зависание, то хорошо бы показать "матрешку" в том порядке, как все вызывалось.

 

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

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

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

По таймерам:

Есть интересные места, но я пошел вариантом наследования класса таймера от событийного:

--/ -----------------------------------------------------------------
class "timer" (event) --/
--/ -----------------------------------------------------------------
function timer:__init(name) super("timer")
  if name and name ~= "" then
    self.__tmr_name = name
  end
end

--/ start(set) event timer and register callback function
--/ call: timer(name):start(func, times(1|3) [,uo])
--/   real-timer(rt): name_timer(1), time_seconds(2) [, params(3)]
--/   game-timer(gt): name_timer(1), time_days(2), time_hours(3), time_minutes(4) [ ,params(5)]
function timer:start(func,...)
  if self.__tmr_name and next{...} then
    Start_Timer(self.__tmr_name,...)
    if not self:registered(func,self.__tmr_name) then
      self:register(func,self.__tmr_name)
    end
  end
end

--/ check event timer ...
--/ call: timer(name):check([params, flag_mode])
function timer:check(...)
  return Check_Timer(self.__tmr_name,...) --/>
end

и есть преимущества в наследовании уже сделанного в ивентах ...

 

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

По разнице используемых операторов понял - спасибо за пояснение, я не обратил внимание на то, что может затираться поле с ранее запомненным зависшим тредом с тем же имененем ...

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

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

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

Вот именно - наследованием. А зачем? Что у них общего? НИЧЕГО.

Если делать ООП, то делать по всем правилам, а не абы как. Потому что таймеры - это генераторы событий, но никак не события.

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

 

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

Посмотрев твой код вижу новые методы типа проверки на зарегистрированность...

В общем, ты пошел старой знакомой дорожкой, а не той, что я закладывала.

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

Ну и конечно же - куда деться от 'uo'. Архинужная вещь.

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

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

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

Ключевое фраза: "А зачем?"

Уже писал ранее, что разница в наших подходах в "чистом" концепте (тут конечно же правила ООП превыше ...) и практического применения концепта к игре с ее кучерявостью.

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

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

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

 

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

Переменное количество параметров, конечно же лучше, чем набор методов для выставления величин (это сарказм был).
Ты упускаешь из вида то, что мне приходится иметь дело с наследуемым кодом (AMK+...) и убрать в одночасье все это непросто, а точнее - просто сесть и переписать весь мод ...

И если я вижу пока пользу и востребованность того же 'uo' (пользователькие параметры) - то почему в связке с основным концептом использование этого так товою отвергается?

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

 

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

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

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

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

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

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

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

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

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

Войти

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

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

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