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

Язык 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
Ссылка на комментарий

Viнt@rь,

вот почему ты ограничиваешь себя стандартным обьемом для сохраняемых данных,

Да потому что:

а) объем одной переменной больше 8кб - хрень полная, ошибка проектирования и с этим точно что-то надо делать.

б) потому что подключение чего либо - танцы с бубном и вообще навешивание приблуд на игру.

в) для конечного пользователя это все не нужно - чем меньше костылей подставляем, тем лучше (как пример, конфигуратор в ОГСЕ, например, или в других модах).

г) использование костылей резко суживает портабельность решения. Не смогут те, у кого нет в моде такой приблуды, использовать его. Смысл тогда?

Это все имхо.

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

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

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

Monnoroch,

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

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

...

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

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

 

И что таки мешает тебе добавить трёхстрочную обёртку, преодолевающую это ограничение? Я бы не рекомендовал таким пользоваться, но это не великое дело - написать эти три строки для себя и использовать.

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

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

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

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

 

Ссылка на комментарий
Если можно, то я для себя сам решу, завязывать мне или нет. ок?

Ты не понял, я имел ввиду что Я завязываю про ассерты. Продолжать ли ТЕБЕ обсуждение, дело твое, мне какая разница?

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

 

Я в любом случае был неправ и грубить не имел права. Прошу прощения.

Malandrinus

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

Опять у вас начался спор о фломастерах. Тут просто конфликт различных взглядов на разработку. Я например поддерживаю malandrinus'a т.к. считаю что лучше я сейчас, в процессе разработки, найду узкое место которое может приводить к вылетам/лагам/переполнениям/просто к ненужным вызовам, чем я потом буду искать эти места. Но опять же это просто разные взгляды и все

Freedom

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

malandrinus,

убрать этот фрагмент и оставить более общий

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

В добавок, в данном случае три строки не помогут: надо отписать общий случай но сохранить частный. То есть соблюдать вложенность.

Я, может, пытаюсь придумать искусственный случай, но в самом деле, кто знает, как будут использовать возможность подписки? Я любитель общих решений :)

И не любитель лезть руками в чужой код, неблагодарное это занятие, может там на четном количестве ошибок в знаке все держится?

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

Monnoroch,

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

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

 

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

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

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

 

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

malandrinus, кстати об этом, а анонимная функция пойдет для решения проблемы?

навроде:

slt = {fun = function() return f() end}

В смысле так же можно?

 

В общем случае сработает ли такое решение:

function duplicate(f)
  return function(...) return f(...) end
end

ASSERT(f ~= duplicate(f),"?")

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

Monnoroch,

анонимная функция пойдет для решения проблемы?

навроде:

slt = {fun = function() return f() end}

Да, эта анонимная функция будет создаваться всякий раз новая. Подписывай сколько угодно раз.

 

 

В общем случае сработает ли такое решение:

function duplicate(f)
  return function(...) return f(...) end
end

Как-то слишком сложно. Дубликат можно сделать так.

function fun1(a,b,c)
end

function fun1_dublicat(...)
    return fun1(...)
end

 

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

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

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

 

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

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

?

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

Коротко - да.

Результатом такого выражения становится последний компонент, подошедший под условие

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

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

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

http://ifolder.ru/28140737

Ах да, делалась она на основе системы malandrinus, из оригинального кода взято обеспечение корректной работы очередей и каменты, так что не надо удивляться :)

И да, спасибо ему за идею.

 

И таки "a or return" не работает, по крайней мере codepad не понимает, потому там такие штуки везде накомментированы, тоже не надо удивляться...

 

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

Как-то слишком сложно.

Если обобщить твой вариант для произвольной функции получится:

function dublicat(f, ...)
    return f(...)
end

Но это странный вариант. Он не создает новую функцию.

А моя функция принимает функцию и возвращает ее копию. А уже копию я могу приписать к тому же сигналу.

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

Изменено пользователем Monnoroch
Ссылка на комментарий
И таки "a or return" не работает, по крайней мере codepad не понимает, потому там такие штуки везде накомментированы, тоже не надо удивляться...

return туда нельзя пихать! Он не может участвовать в логических операциях, так как не является вычислимым выражением, является конструкцией языка.

Надо писать

 return a or f()

Вот так - правильно. Вернет либо а, либо результат выполнения функции f в случае, если a равно false или nil

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

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

xStream, Да, я уже это понял :)

Просто в D есть такая штука, что выражения типа void туда пихать можно, в результате всё expression преобразуется в statement и получаются такие вот красивые ветвления.

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

Вот интересно, почему local sim = alife() и далее по тексту - можно писать, а с vector() такое не прокатывает ?

Универсальное правило есть какое-то ?

 

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

Dennis_Chikin,

Вот интересно, почему local sim = alife() и далее по тексту - можно писать, а с vector() такое не прокатывает ?

Не совсем понятно, что ты имеешь в виду. Что ты хочешь от сохранённого на потом вектора?

Вообще же, когда ты пишешь alife() ты вызываешь функцию получения глобального объекта класса alife_simulation. Этот объект существует постоянно (по крайней мере в пределах одной загруженной игры). Если же пишешь vector(), то это вызов конструктора класса vector с созданием нового экземпляра объекта. Не знаю, отвечает ли это на вопрос...

 

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

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

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

 

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

xStream, вот вариант (проверенный в игре) для 'skeleton' в формате ACDC и без внешней функции:

--/ -----------------------------------------------------------------
class "net_cse_ph_skeleton" (net_base) --/ has derived
--/ -----------------------------------------------------------------
function net_cse_ph_skeleton:__init(obj,skip)
    super(obj, bit_or(skip, skip_props.update), "cse_ph_skeleton")
    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.props_bones = { --/#+#
        { name = 'bones_mask',          type = 'q8v',   default = {0,0,0,0,0,0,0,0}, len = 8 }, --/'u8v8'
        { name = 'root_bone',           type = 'u16',   default = 0 },
        { name = 'ph_angular_velosity', type = 'f32v3', default = vector() },
        { name = 'ph_linear_velosity',  type = 'f32v3', default = vector() },
        { name = 'bones_count',         type = 'u16',   default = 0 } --/#?# 'bone_count'
    }
    self.props_bone = { --/#+#
        { name = 'ph_position',         type = 'q8v',   default = {0,0,0},   len = 3 }, --/'q8v3'
        { name = 'ph_rotation',         type = 'q8v',   default = {0,0,0,0}, len = 4 }, --/'q8v4'
        { name = 'enabled',             type = 'u8',    default = 1}
    }
    self.updprops = {}
end
function net_cse_ph_skeleton:_read(ret,stpk,updpk)
    self:_read_bases(ret,stpk,updpk)
    
    if self.skip ~= skip_props.state then
        for _,prop in ipairs(self.props) do
            ret[prop.name] = this["_r_"..prop.type](stpk, prop.len)
        end
        if bit_and(ret.skeleton_flags, 4) == 4 then --/ check 'skeleton'
            for _,prop in ipairs(self.props_bones) do --/ read 'bones'
                if ret[prop.name] ~= 'bones_count' then
                    ret[prop.name] = this["_r_"..prop.type](stpk, prop.len)
                end
            end
            if ret.bones_count > 0 then --/ read 'bone': ...
                ret["bones"] = {}
                for i=1,ret.bones_count do
                    local bone = {}
                    for _,prop in ipairs(self.props_bone) do
                        bone[prop.name] = this["_r_"..prop.type](stpk, prop.len)
                    end
                    table.insert(ret["bones"], bone)
                end
            end
        end
    end
end
function net_cse_ph_skeleton:_write(data,stpk,updpk)
    self:_write_bases(data,stpk,updpk)
    
    if self.skip ~= skip_props.state then
        for _,prop in ipairs(self.props) do
            if prop.name == "skeleton_name" and self.obj and (self.obj:clsid() == clsid.script_heli or self.obj:clsid() == clsid.car_s) and data.skeleton_name == prop.default then
                this["_w_"..prop.type](stpk, "idle") --/#!# change '$editor' for cars & helicopters
            else
                this["_w_"..prop.type](stpk, data[prop.name] or prop.default or 0)
            end
        end
        if bit_and(data.skeleton_flags, 4) == 4 and data.bones_count then --/ check 'bones'
            for _,prop in ipairs(self.props_bones) do --/ write 'bones'
                this["_w_"..prop.type](stpk, data[prop.name] or prop.default or 0)
            end
            if data.bones then --/ write 'bone' ...
                for _,bone in ipairs(data.bones) do
                    for _,prop in ipairs(self.props_bone) do
                        this["_w_"..prop.type](stpk, bone[prop.name] or prop.default or 0)
                    end
                end
            end
        end
    end
end
--/ -----------------------------------------------------------------

 

Также, может быть чем-то глянется вариант компоновки для типовых чанков и CTime:

--/ -------------------------
--/ prop.type: variable chunk:: in: datatype: u8|u16|s32|floor|bool|stringZ|... [default: nil=>'u8' (по-байтно)]
--/ -------------------------
--/ read:: in: packet, lenght [,datatype [,table]] | out: table
local _r_chunk = function(pk,len,dt,tbl)
    if len and len > 0 then
        if not (tbl and type(tbl) == 'table') then tbl = {} end
        local func = this["_r_"..(dt or 'u8')]
        for i=1,len do
            table.insert( tbl, func(pk) )
        end
    end
    return tbl or {} --/>
end
--/ write:: in: packet, table [,datatype]
local _w_chunk = function(pk,tbl,dt)
    if type(tbl) == 'table' and next(tbl) then
        local func = this["_w_"..(dt or 'u8')]
        for _,v in ipairs(tbl) do
            func(pk,v)
        end
    end
end
--/ -------------------------
--/ prop.type: fixed chunks
--/ -------------------------
_r_q8v     = function(pk,len) return _r_chunk(pk,len,        'u8' ) end
_r_u8v8    = function(pk)     return _r_chunk(pk,8,          'u8' ) end --/#?# => 'r_ctime'
_r_l32u16v = function(pk)     return _r_chunk(pk,pk:r_s32(), 'u16') end
_r_l32u8v  = function(pk)     return _r_chunk(pk,pk:r_s32(), 'u8' ) end
_r_l8u16v  = function(pk)     return _r_chunk(pk,pk:r_u8 (), 'u16') end
_r_l8u8v   = function(pk)     return _r_chunk(pk,pk:r_u8 (), 'u8' ) end
_r_l16u8v  = function(pk)     return _r_chunk(pk,pk:r_u16(), 'u8' ) end

_w_q8v     = function(pk,tbl)                _w_chunk(pk,tbl,'u8' ) end
_w_u8v8    = function(pk,tbl)                _w_chunk(pk,tbl,'u8' ) end --/#?# => 'w_ctime'
_w_l32u16v = function(pk,tbl) pk:w_s32(#tbl) _w_chunk(pk,tbl,'u16') end
_w_l32u8v  = function(pk,tbl) pk:w_s32(#tbl) _w_chunk(pk,tbl,'u8' ) end
_w_l8u16v  = function(pk,tbl) pk:w_u8 (#tbl) _w_chunk(pk,tbl,'u16') end
_w_l8u8v   = function(pk,tbl) pk:w_u8 (#tbl) _w_chunk(pk,tbl,'u16') end
_w_l16u8v  = function(pk,tbl) pk:w_u16(#tbl) _w_chunk(pk,tbl,'u8' ) end
--/ -------------------------
--/ prop.type: CTime
--/ -------------------------
_r_ctime = function(pk)
    tbl.ctime = utils.r_CTime(pk) --/< userdata|0|nil
    return tbl --/>
end
_w_ctime = function(pk,tbl)
    if type(tbl.ctime) == 'userdata' then
        utils.w_CTime(pk, tbl.ctime)
    elseif iSSVer < 8 then --/ SHoC
        pk:w_u8(0)
    elseif not tbl.ctime then --/ CS|CoP
        pk:w_u8(-1)
    else
        utils.w_CTime(pk, game.CTime()) --/#?# TODO: проверить
    end
end
--/ -------------------------

(примечание: некоторые вкрапления в кодах - особенность мода, а не для общего употребления)

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

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

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

Не, каша. Скелет - отдельная неделимая сущность, представляющая собой одно свойство.

ИМХО код гораздо более громоздкий вышел

 

Что касается чанков - это дело барское. Непонятно, как это относится к исходной библиотеке. Это уже доп функционал. Реализуется, кстати, легко с помощью tail_data.

Скелетон я проверила в той версии, что сейчас лежит. Хук для вертолетов тоже приложен. Считаю эту версию пока конечной. За мануал вполне идет описание из шапки.

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

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

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

Твой нынешний вариант тоже гонял в игре, рабочий. Оба варианта идентичны по результату.

Посто данный подход позволяет внутри класса замыкать именно его нюансы и следовать формату ACDC, а не выводить каждый раз во внешнюю примочку. Это вполне может быть актуальным, если далее подстраивать/расширять коды под версии игры (+ЧН, +ЗП) и дополнять недостающие классы.

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

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

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

Тогда уж вноси шейпы и кастомдату в соответствующие пакеты, загромождай код. :-P

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

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

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

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

 

По делу: Похоже в "-- item packet hooks" (класс cse_alife_item) есть неточность. По условию 'num_items' == 0 должны отсекаться чтение/запись всех(!) последующих пропертей, а в настоящей реализации отсекаются (в skip_updprops) только последние два, обусловленные своими доп.условиями. Более павильно вроде бы так (для _read):

  --/ item packet hooks
  local skip_updprops = {}
  for _,prop in ipairs(self.updprops) do
    if not skip_updprops[prop.name] then
      ret[prop.name] = this["_r_"..prop.type](updpk, prop.len)
      if prop.name == 'num_items' then
        if ret.num_items == 0 then
          break
        else
          if bit_and(ret.num_items, 64) ~= 64 then
            skip_updprops.ph_angular_vel = true
          end
          if bit_and(ret.num_items, 128) ~= 128 then
            skip_updprops.ph_linear_vel = true
          end
        end
      end
    end
  end

(для _write по аналогии)

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

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

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

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

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

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

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

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

Войти

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

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

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