Dennis_Chikin 3 658 Опубликовано 4 Января 2015 Поделиться Опубликовано 4 Января 2015 (изменено) С чего начинать и где взять. Установка 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 Изменено 2 Марта 2015 пользователем Kirgudu Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Ссылка на комментарий
kamikazze 266 Опубликовано 11 Января 2012 Поделиться Опубликовано 11 Января 2012 Artos 1. Упрощен/оптимизирован процесс записи/чтения нет-пакетов объектов хранения. Никаких лишних операций. 2. Операция по сериализации хранимых в хранилище таблиц оставлена только непосредственно при сохранении таблий в объекты хранения., что дало возможность оптимизировать оперции чтеия/записи в собственно хранилище. Блин, а. Артос, не надо чинить то, что работает, пожалуйста. В твоё текущем варианте есть пара злобных привнесенных косяков: Во-первых не ясно, когда хранилище таки полностью загрузилось, в результате все равно надо ждать спавна актора. Какой тогда смысл был переделывать, ммм? Во-вторых эта твоя "оптимизация" привела к тому, то ты не узнаешь, если сериализованная таблица вылезла за размеры хранилища. А люди ведь возьмут и будут пользоваться, не будучи в курсе возможных последствий. Отладчик и скриптер мода OGSE. Автор схемы "Компаньоны", стреляющего БТРа и многих других полезностей Ссылка на комментарий
Andrey07071977 18 Опубликовано 11 Января 2012 Поделиться Опубликовано 11 Января 2012 malandrinus, Как я понимаю, класс может иметь только один метод-подписчик: mt.__call = self.method_to_call Как быть в ситуациях когда в классе несколько методов которые необходимо подписать на разные события? Например, есть класс "actor_hit_effect", в нем два метода-подписчика - один на actor_hit, другой на item_use. Или же я что-то недопонял? Ссылка на комментарий
xStream 86 Опубликовано 11 Января 2012 Поделиться Опубликовано 11 Января 2012 Andrey07071977, Как быть в ситуациях когда в классе несколько методов которые необходимо подписать на разные события? Например, есть класс "actor_hit_effect", в нем два метода-подписчика - один на actor_hit, другой на item_use. Или же я что-то недопонял? Использовать замыкания. Я раньше писала, как это делать. Я не знаю, зачем такие сложности Саша придумал Вот вариант: function bind_method_x(obj) return function (...) return obj:method_x(...) end end local funct = bind_method_x(megaobject) --в переменной funct окажется функция, которую можно передать куда угодно. Все, кто стоит на моем пути: идите нахрен и там погибните! © Ссылка на комментарий
Andrey07071977 18 Опубликовано 11 Января 2012 Поделиться Опубликовано 11 Января 2012 (изменено) xStream, спасибо, перечитаю твой пост и пройдусь по замыканиям, пока что я туплю не по детски на эту тему... Такое впечатление, что крутится где-то в голове но пока не могу расставить точки над i. То есть, для моего примера необходимо создать два метода? function object_execute(obj) local _proxy = obj local function _call(...) return _proxy:execute(...) end return _call end function object_execute_1(obj) local _proxy = obj local function _call(...) return _proxy:execute_1(...) end return _call end Да, я знаю про что ты говорила Понял, спасибо. Но теорию все равно нужно поднатаскать.. уж больно много пробелов Изменено 11 Января 2012 пользователем Andrey07071977 Ссылка на комментарий
xStream 86 Опубликовано 11 Января 2012 Поделиться Опубликовано 11 Января 2012 Andrey07071977, http://www.amk-team.ru/forum/index.php?s=&...st&p=661284 Там более развернуто, с созданием переменных, но это не обязательно. Пример выше - гораздо компактнее. Но делает то же самое. Добавлено через 5 мин.: Да, правильно. Можно, правда, еще короче: function object_execute(obj) return function (...) return obj:execute(...) end end function object_execute_1(obj) return function (...) return obj:execute_1(...) end end Все, кто стоит на моем пути: идите нахрен и там погибните! © Ссылка на комментарий
Andrey07071977 18 Опубликовано 11 Января 2012 Поделиться Опубликовано 11 Января 2012 (изменено) Kamikazze, Во-вторых эта твоя "оптимизация" привела к тому, то ты не узнаешь, если сериализованная таблица вылезла за размеры хранилища. Разве это не проверка перед сохранением? for key, val in pairs(storage) do lua_type = type(val) num_type = allowed_types_rev[lua_type] err = num_type == nil if not err then -- calculate variable len for saving elm_len = 1 + string.len(key) + 1 if lua_type == 'boolean' then elm_len = elm_len + 1 elseif lua_type == 'number' then elm_len = elm_len + 4 else if lua_type == 'table' then val,err = table.serialize(val) if err or val:len() >= max_packet_len then --/ тип данных или длина строки недопустимы --log("save:var_name=[%s],err=[%s]:<%s>", key, err, "Warning!") val,err = "",true end end elm_len = elm_len + val:len() + 1 end if not err then --/ check room to save if len + elm_len > max_packet_len then -- element is full of data -- create new element to store variables -- ugly hook, but fastest solution :) tail_pk = new_storage_element() len = elm_len else -- still have room to save len = len + elm_len end --write variable to tail tail_pk:w_u8(num_type) tail_pk:w_stringZ(key) if lua_type == 'boolean' then tail_pk:w_u8(val) elseif lua_type == 'number' then tail_pk:w_float(val) else tail_pk:w_stringZ(val) end end end end Изменено 11 Января 2012 пользователем Andrey07071977 Ссылка на комментарий
Artos 99 Опубликовано 11 Января 2012 Поделиться Опубликовано 11 Января 2012 (изменено) kamikazze, если ты не понял ни цели "для чего выложено", но того что же сделано, зачем же сразу наезжать? Мы тут обсуждаем или ругаем? Если говоришь о "злобных привнесенных косяков" - ну так и ткни носом, а не голословно ругай и ... подучи мат.часть вначале. 1. Собственно ничего и НЕ чиню, а делаю свою реализацию (считай сделал) на базе материалов xStream и собственных наработок. Как я понял, у malandrinus'а аналогичное. 2. Если тебе непонятно как работает - поясню, для этого и вложил второй рабочий на 100% вариант, чтобы если в первом упустил/очепятался, то по второму все можно проверить. Основное отличие моей реализации в том, что почти никаких внешних вмешательств в функционирование хранилища не требуется. 1. Само хранилице (массив) расположено в _G и готово к записи/чтению сразу по запуску игры. Естественно оно первоначально пустое. 2. По мере игры в хранилище поступают различные данные различных типов данных. Специально убрал сериализацию таблиц, дабы и не усекать возможносьт хранения в общем хранилище даже тех типов данных, которые не будут сохранены. Мне пока такое не требуется (привык не хранить в pstor'ах лишнего), но не вижу надобности в таком ограничение в самой игре. Само собою, в сэйвы невалидные типы данных не сохранятся. 3. По событию "сохранить данные из хранилища", которое я у себя делаю или по окончанию сэйва актора или даже по сэйву его КПК - включается цикл сохранения. Расписывать несколько объектов для сохранения нет смысла (пока) и рассмотрим один. - Создается объект и им порожденный tail-пакет, которому устанавливаются необходимые позиции чтения и записи. Именно этот подготовленный tai-пакет передается в менеджер сохранения данных хранилища. - В tail-пакет (со 2-ой позиции) записываются необходимые данные - до его заполнения (<8кБ) и пакет оставляется в покое(!), т.е. никаких принудительных операций сторонними нет-писалками с ним не делается. Хранилище сохраняет далее в следующий созданный аналогчный tail-пакет ... Обращаю внимание, что объекты хранения (кастом-стороджы) в это время никак не задействованы. - Если игра именно прекрашается, т.е. "* Saving objects..." - объекты хранения движком сохраняются, что вызывает для каждого метод STATE_Write, в который добавлен копировщих STATE_Copying. Эта связка приводит к тому, что штатным вызовом сохранения объекта убиваются оба зайца, сохраняется как пакет объекта, так и перезаписанный в него tail-пакет этого объекта(!). Т.к. позиции чтения выставлена и имеется конец записи - в объект копируются именно данные из хранилища. Все,объект(ы) сохранены. - Если был квик сэйв - то оставшиеся в игре объекты хранения могут быть баластом, который будет удален перед следующем сохранении и цикл повторится заново или их можно удалить по таймеру через неск. секуннд. Хранилище в это времы продолжает работу в штатном режиме. Теперь о заполнении хранилища при старте игры: - Т.к. имеется серверный класс 'se_custom_storage' с его on_register и STATE_Read + STATE_Copying. В момент загрузки объектов в иру ("* Loading objects...") загружаются и сторадж-объекты. Для каждого создается tail-пакет и движком вызывается STATE_Read. При этои из нетпакета объекта в tail-пакет считываются ранее сохраненные данные хранилища. - по on_register tail-пакет передается считывателю данных в хранилище. Опять, никакие сторонние манипуляции сторонними нет-писалками не требуются. Т.о. хранилще заполняется ранее сохраненными данными по факту появления в игре каждого объекта хранения и ПОЛНОСТЬЮ восстановлено к моменту подключения сервера к игре (Сервер: Соединяемся...). С этого момента хранилище готово выдавать все те данные, которые были в нем в момент сохранения в сэйв. Хочешь ждать спавна актора - твое дело, но можно и не дожидаться, а еще до его спавна пользоваться сохраненными данными. Восстанавливать настройки модулей, таймеры и пр. ... Так что и сам уже пользуюсь и думаю и другие будут пользоваться! Изменено 11 Января 2012 пользователем Artos "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Ссылка на комментарий
xStream 86 Опубликовано 11 Января 2012 Поделиться Опубликовано 11 Января 2012 Andrey07071977, Разве это не проверка перед сохранением? А смысл мне от этой проверки? Это проверяется при сохранении и получаем ошибку. Функция set была изначально организована так, что возвращала булевое значение - успешность помещения переменной в хранилище. Тогда, программист, получив false, мог бы принять меры - уменьшить как-то размер таблицы. (Черт! Надо еще длину у строки проверять!) А так. Он запихнул, а потом огреб ошибку, и как ее обрабатывать? Все, кто стоит на моем пути: идите нахрен и там погибните! © Ссылка на комментарий
Artos 99 Опубликовано 11 Января 2012 Поделиться Опубликовано 11 Января 2012 По поводу сериализации уже дали реплику. Зачем ограничивать само хранилище, когда это делать нужно только для объектов хранения! Ну а если нужно кому в процессе игры подобное контролировать, то не таким же драконовским способои и конечно же опционально. "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Ссылка на комментарий
Malandrinus 615 Опубликовано 11 Января 2012 Автор Поделиться Опубликовано 11 Января 2012 Andrey07071977, Как быть в ситуациях когда в классе несколько методов которые необходимо подписать на разные события? Например, есть класс "actor_hit_effect", в нем два метода-подписчика - один на actor_hit, другой на item_use. Как раз для этого есть вариант с указанием self local hit_effect = actor_hit_effect() sm:subscribe({signal = "on_actor_hit", self = hit_effect, fun = hit_effect.on_hit}) sm:subscribe({signal = "on_item_use", self = hit_effect, fun = hit_effect.on_use}) или даже так class "actor_hit_effect" function actor_hit_effect:__init() self.sm = ogse_signals.get_mgr() self.desc_on_hit = {signal = "on_actor_hit", self = self, fun = self.on_hit} self.sm:subscribe(self.desc_on_hit) self.desc_on_use = {signal = "on_item_use", self = self, fun = self.on_use} self.sm:subscribe(self.desc_on_use) end function actor_hit_effect:unsubscribe_itself() self.sm:unsubscribe(self.desc_on_hit) self.sm:unsubscribe(self.desc_on_use) end вариант с функциональным классом - это в сущности редко нужные изыски. С точки зрения Lua функциональный класс - это та же функция. Поскольку можно подписать функцию, то можно и функциональный класс. Только и всего. xStream, Я не знаю, зачем такие сложности Саша придумал Нет там никаких сложностей. Как раз эта фича обеспечивается всего парой дополнительных строк. Передаётся первым аргументом self при его наличии, и сравнение дескрипторов слотов на равенство включает ещё и сравнение self. Плагины Total Commander для работы с игровыми архивами: Архиваторный плагин (для работы с одиночным архивом): link1 link2 Системный плагин (для распаковки установленной игры): link1 link2 Ссылка на комментарий
Artos 99 Опубликовано 11 Января 2012 Поделиться Опубликовано 11 Января 2012 (изменено) Это проверяется при сохранении и получаем ошибку Не получаем ошибку, а получаем предупреждение, кпо которому можно при необходимости и абортнуть. Это все же разница. То, что не должно попасть в сэйвы - не попадет, и это забота модмейкера. Кому-то на такие данные и наплевать, а кто-то озаботится и сам не будет хранить в общем хранилище непотребное. Ну а озабоченным ничего не мешает два типа set'ов себе сделать: обычный и с сериализацией (типа set_safe) и будет ему счастье отлавливать баги. Зачем же боясь аварии всегда ехать со скоростью 40 км/час, когда штатно можно можно и под 80 .. ;-) Изменено 11 Января 2012 пользователем Artos "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Ссылка на комментарий
xStream 86 Опубликовано 11 Января 2012 Поделиться Опубликовано 11 Января 2012 (изменено) Саш, дополнительные параметры в инетрфейсе, использование метатаблиц - это не сложности? По сравнению с одним единственным замыканием - еще какие. Изменено 11 Января 2012 пользователем xStream Все, кто стоит на моем пути: идите нахрен и там погибните! © Ссылка на комментарий
Andrey07071977 18 Опубликовано 11 Января 2012 Поделиться Опубликовано 11 Января 2012 (изменено) Что если проверять при каждом перемещении в хранилище на этапе разработке/тестировании - по идее, все bottlenecks должны быть найдены на этих стадиях. А уже в финале оставить лишь проверку перед сохранением, в крайнем случае какие-то данные не сохранятся. malandrinus, примерно так и преставлял, потом приведенный пример сбил с толку. class "some_luabind_class" function some_luabind_class:__init() local mt = getmetatable(self) mt.__call = self.method_to_call end function some_luabind_class:method_to_call(arg1, arg2) end local slot_desc = {signal = "signal_name", fun = some_luabind_class()} Изменено 11 Января 2012 пользователем Andrey07071977 Ссылка на комментарий
xStream 86 Опубликовано 11 Января 2012 Поделиться Опубликовано 11 Января 2012 Andrey07071977, прикол в том, что боттлнека, кстати, не будет при таком подходе: при set производится одна сериализация, при сохранении в "оптимизированном" варианте - при сохранении сериализуется все. В первом подходе нагрузка распределена по времени. И влияние на производительность оказывает небольшое. Зато мы сразу предупреждаем программиста - у тебя тут гавно, срочно принимай меры. Все, кто стоит на моем пути: идите нахрен и там погибните! © Ссылка на комментарий
Malandrinus 615 Опубликовано 11 Января 2012 Автор Поделиться Опубликовано 11 Января 2012 xStream, Саш, дополнительные параметры в инетрфейсе, использование метатаблиц - это не сложности? По сравнению с одним единственным замыканием - еще какие. Да нет там никаких метатаблиц. Я же говорю, с функциональным классом - это изыски, побочный эффект и в общем и не нужно. А вот насчёт указания self, чего там мудрёного то? Ну указать объект надо, так а что такого? Есть объект, есть его метод, так и надо при подписке указать объект и метод. Если эта идея вызывает запредельный ступор при использовании, то я уже не знаю о чём тут говорить. Однако, никто не мешает это не использовать. Как я говорил, это не усложняет реализацию ни на йоту, и при неиспользовании никому не мешает. Andrey07071977, потом приведенный пример сбил с толку Там же был пример с обычным методом. Разве нет? Плагины Total Commander для работы с игровыми архивами: Архиваторный плагин (для работы с одиночным архивом): link1 link2 Системный плагин (для распаковки установленной игры): link1 link2 Ссылка на комментарий
Andrey07071977 18 Опубликовано 11 Января 2012 Поделиться Опубликовано 11 Января 2012 (изменено) malandrinus, если с обычном методом ты имеешь ввиду пример с глобальной функцией - то там все понятно. Не совсем понял про методы класса - думаю имеет смысл перенести пример, который ты привел позже, в первый пост. Пример довольно наглядный Изменено 11 Января 2012 пользователем Andrey07071977 Ссылка на комментарий
Artos 99 Опубликовано 11 Января 2012 Поделиться Опубликовано 11 Января 2012 (изменено) Уж если разговор о работе с хранилищем, а не о сохранении записи, то ... мною НЕ используется сериализатор, а используется компрессор-сериализатор, что дает (даст) выигрыш более 40% на каждый объект хранения. Т.о. таблица, не влезающая в 8кБ сериализатром, вполне может быть сохранена без усечений и абортов игры. И давайте не подменять понятия. Все же забота о том, чтобы в хранилище не поступали заведомо большие куски - это забота модмейкера, а не хранилища. Мне вообще непонятно какие же объемы и чего могут привести к переполнению даже одного сторадж-объекта. Ну а с компрессией - нужно постараться. Хранилище должно надежно функционировать и не давать сбоев, а не заниматься воспитанием модмейкера. И, кину камень в ваш огород: В моем варианте в хранилище не попадут ни большие таблицы, ни большие строки, проверка длины которых в ваших вариантах с сериализатором НЕ предусмотрена и это (большая строка) обрушит объект хранения (сэйв)! Конечно сохранять строку более 8кБ врядли кому понадобится, но ... давайте уж последовательно. Озаботились предупреждать нерадивых о таблицах, так чем же строки вам глянулись и не требуют проверки? ;-) Изменено 11 Января 2012 пользователем Artos "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Ссылка на комментарий
Andrey07071977 18 Опубликовано 11 Января 2012 Поделиться Опубликовано 11 Января 2012 Artos, компрессор-сериализатор это о котором ты здесь писал? Ссылка на комментарий
xStream 86 Опубликовано 11 Января 2012 Поделиться Опубликовано 11 Января 2012 Саш, peace Просто ты привел такие примеры. Ну а насчет интерфейсов я все равно настаиваю, что они должны быть как можно проще и как можно меньше вариаций иметь Все, кто стоит на моем пути: идите нахрен и там погибните! © Ссылка на комментарий
Malandrinus 615 Опубликовано 11 Января 2012 Автор Поделиться Опубликовано 11 Января 2012 Andrey07071977, имеет смысл перенести пример, который ты привел позже, в первый пост. И тем не менее, пример там есть. Последний по счёту. Впрочем, ты прав, заменю на более поздний. Только уже завтра... Плагины Total Commander для работы с игровыми архивами: Архиваторный плагин (для работы с одиночным архивом): link1 link2 Системный плагин (для распаковки установленной игры): link1 link2 Ссылка на комментарий
Рекомендуемые сообщения
Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий
Комментарии могут оставлять только зарегистрированные пользователи
Создать аккаунт
Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!
Зарегистрировать новый аккаунтВойти
Есть аккаунт? Войти.
Войти