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

Язык Lua. Общие вопросы программирования


Malandrinus

Рекомендуемые сообщения

Уважаемое сообщество, хотел бы поинтересоваться Вашим мнением по такому вопросу:

Все видели, наверное, мод автопаузы, который использует инжектор кода через подмену, например, апдейта актора. Но 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, описанная выше.

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

Поделиться этим сообщением


Ссылка на сообщение

 

 

можно только после инициализации класса

Перенеся сохранение функции в модуль - избавился от ошибки.

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

Поделиться этим сообщением


Ссылка на сообщение

 что он должен делать

- для простоты , все что дальше я буду писать - будет касаться 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

 

тут подмена вызова нажатий клавиш в главном меню.

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

Поделиться этим сообщением


Ссылка на сообщение

Вопрос по метатаблицам

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.

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

Поделиться этим сообщением


Ссылка на сообщение
17 минут назад, abramcumner сказал:

Это присваивание новой таблицы, у которой нет метатаблицы.

т.е. без какого то лишнего шага не обойтись?

например, псевдокод:

rawdata={["dsdsd"]=true}

setmetatable(data,{__index,__newindex})

copy(data,rawdata)

 

 

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

Поделиться этим сообщением


Ссылка на сообщение
  • Недавно просматривали   0 пользователей

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