Winsor 177 Опубликовано 18 Февраля 2016 (изменено) Уважаемое сообщество, хотел бы поинтересоваться Вашим мнением по такому вопросу: Все видели, наверное, мод автопаузы, который использует инжектор кода через подмену, например, апдейта актора. Но xray считает по другому, и на такие попытки разместить именно в коде класса функцию он уверенно сообщает, что "RUNTIME ERROR - no static '_update' in class 'actor_binder'". Вот меня и интересует - 1) Отходит ли от стандарта языка такая технология инжектора кода? 2) если язык это поддерживает - в данном случае luabind "не прав" (ибо сообщение о ошибке - выдает именно он)? 3) игнорировать ли мне такое сообщение или переписать код в соответствие со стандартами языка? Благодарю за Ваше мнение! не столь секретен, чтобы ограничиваться лишь туманными намеками - эээ... да никаких секретов... у меня в тексте сообщение так и написано - "мод автопаузы", впервые мне встретился, наверное в НС в каком то репаке. в ооп еще был. мод, который после загрузки добавляет паузу на нажатие любой клавиши (ТЧ). inj.script - там есть такой код, который не нравиться xray 1.0007 local function inj_main(func_name,flag,fn,narg) if not _G.bind_stalker.actor_binder["_"..fn] then _G.bind_stalker.actor_binder["_"..fn] = {} if narg==1 then _G.bind_stalker.actor_binder["_"..fn][1] = _G.bind_stalker.actor_binder[fn] _G.bind_stalker.actor_binder[fn] = function(...) for _,f in pairs (_G.bind_stalker.actor_binder["_"..fn]) do f(...) end end else _G.bind_stalker.actor_binder[fn.."_"] = _G.bind_stalker.actor_binder[fn] or function()end _G.bind_stalker.actor_binder[fn] = function(...) local arg={...} _G.bind_stalker.actor_binder[fn.."_"](...) for _,f in pairs (_G.bind_stalker.actor_binder["_"..fn]) do f(arg[narg]) end end end end _G.bind_stalker.actor_binder["_"..fn][func_name] = loadstring('return _G["'..string.gsub(flag and func_name or "_","%.",'"]["')..'"]')() end function inj_update(func_name,flag) inj_main(func_name,flag,"update",1) end в данном случае вызов в классе актора update подменяется на 2-а вызова , один - сохраненная функция (оригинальный actor_binder.update), второй - функция, переданная как параметр. Вот собственно. если такой подход применяется к функции в модуле - движок не возражает, если к классу - вызывает runtime error, описанная выше. Изменено 18 Февраля 2016 пользователем Winsor Поделиться этим сообщением Ссылка на сообщение
Winsor 177 Опубликовано 18 Февраля 2016 можно только после инициализации класса Перенеся сохранение функции в модуль - избавился от ошибки. данную подмену необходимо делать после загрузки модуля но до инициализации класса , методы которого пытаемся подменить. Движок создает, например, биндер актора один раз, и любые подмены после вызова __init ни к чему не приводят. Но это частности. Интересовала вообще корректность такого подхода, насколько он оправдан. Поделиться этим сообщением Ссылка на сообщение
Winsor 177 Опубликовано 19 Февраля 2016 (изменено) что он должен делать - для простоты , все что дальше я буду писать - будет касаться bind_stalker.actor_binder.update. по логике автора - код должен заменить вызов этой функции на функцию автора, без изменения непосредственно кода самого actor_binder с сохранением старого функционала. вот это вот что и зачем - это и есть непосредственно сама замена (fn=="update" ), внутри которой и вызывается свой код + сохраненная версия. по поводу цикла - ничего не скажу. Возможно автор предполагал через дополнительные параметры при первоначальном инжекте добавлять в таблицу t несколько функций, и таким образом их вызывать. в том же скрипте автопаузы есть local function inj_mm_on_kbd(func_name) local name = "ap_mm_on_kbd" _G[name] = _G.ui_main_menu.main_menu.OnKeyboard _G.ui_main_menu.main_menu.OnKeyboard = function(...) local arg={...} if not loadstring('return _G["'..string.gsub(func_name,"%.",'"]["')..'"]')()(arg[1],arg[2],arg[3]) then return _G[name](...) end return true end end тут подмена вызова нажатий клавиш в главном меню. Изменено 19 Февраля 2016 пользователем Winsor Поделиться этим сообщением Ссылка на сообщение
Winsor 177 Опубликовано 22 Мая 2018 (изменено) Вопрос по метатаблицам local data=setmetatable({},{ __tostring = function() return "data_table_name" end, }) log("1 "..tostring(data)) data={["dsdsd"]=true} log("2 "..tostring(data)) Вывод 1 data_table_name 2 0A0EC4C8 т.е. при инициализации таблицы новыми данными ее метатаблица затирается. если делать setmetatable после инициализации - не вызываются _index,__newindex. каким образом можно избежать такого эффекта? очень не хочется писать отдельные циклы заполнения таблицы с метаданными... p.s. все это вызывается из под движка ТЧ 1.0007 p.s.s. само собой, можно написать и так: local data=setmetatable({["dsdsd"]=true},{ __tostring = function() return "data_table_name" end, }) но все равно не вызываются события _index,__newindex у таблицы data. Изменено 22 Мая 2018 пользователем Winsor Поделиться этим сообщением Ссылка на сообщение
Winsor 177 Опубликовано 22 Мая 2018 (изменено) 17 минут назад, abramcumner сказал: Это присваивание новой таблицы, у которой нет метатаблицы. т.е. без какого то лишнего шага не обойтись? например, псевдокод: rawdata={["dsdsd"]=true} setmetatable(data,{__index,__newindex}) copy(data,rawdata) Изменено 22 Мая 2018 пользователем Winsor Поделиться этим сообщением Ссылка на сообщение