Serfer_78 Posted August 8, 2017 Share Posted August 8, 2017 (edited) import game def hookOnGeometryMapped(spaceID, path): hookedOnGeometryMapped(spaceID, path) print 'mapName: %s, mapPath: %s' % (path.split('/')[-1], path) hookedOnGeometryMapped = game.onGeometryMapped game.onGeometryMapped = hookOnGeometryMapped Интересно , а что происходит в коде при хуке функции, не пойму что делает эта строка hookedOnGeometryMapped = game.onGeometryMapped а в момент обращения к жертве вместо ее кода подсовывается хук функция game.onGeometryMapped = hookOnGeometryMapped или я не так понял? , и получается что пока мод на месте функция будет хукаться ? Edited August 8, 2017 by Serfer_78 @ Quote Link to comment Short link Share on other sites More sharing options...
GPCracker Posted August 9, 2017 Share Posted August 9, 2017 (edited) или я не так понял? , и получается что пока мод на месте функция будет хукаться ?Любая переменная есть ссылка. hookedOnGeometryMapped = game.onGeometryMappedЭто сохранение в локальную переменную ссылки на оригинальную функцию. game.onGeometryMapped = hookOnGeometryMappedЭто сохранение в оригинальное место ссылки на твою функцию, хук.Внутри хука ты вызываешь сохраненный оригинал. Схема без хука - вызывающий код получает ссылку на функцию-оригинал из game.onGeometryMapped и вызывает ее. Схема с хуком - вызывающий код получает ссылку на функцию-хук из game.onGeometryMapped и вызывает ее. Внутри функции-хука выполняется оригинал и еще немного кода. Важно!!! Не забываем, что функция часто возвращает какое-то значение. Поэтому нужно его получить (сохранить) при вызове оригинала и вернуть из хука!!! Иначе оригинальный код будет работать некорректно. Т.е. def hookOnGeometryMapped(spaceID, path): result = hookedOnGeometryMapped(spaceID, path) print 'mapName: %s, mapPath: %s' % (path.split('/')[-1], path) return resultВ случае, если функция ничего не возвращает, считается, что она возвращает None. Если ты выполнишь "проброс возврата" для такой функции - ничего плохого не случится. А вот если забудешь, там где он необходим (где функция возвращает не None), получишь некоторое количество лишних проблем. Поэтому рекомендую всегда пробрасывать возврат вне зависимости от того, что возвращает функция. Edited August 9, 2017 by GPCracker 2 @ Quote Link to comment Short link Share on other sites More sharing options...
ShuraBB Posted August 9, 2017 Share Posted August 9, 2017 (edited) >Тут бы по идее потоки запилить но пока не созрел как правильно это реализовать. import threading from Queue import Queue class UPDThreading(object): def __init__(self): self.Data = Queue() self.thread = threading.Thread(target = self.SendData) self.thread.setDaemon(True) self.thread.setName('Send UPD Data') self.thread.start() def SendData(self): while True: Message = self.Data.get() try: socket.socket(socket.AF_INET, socket.SOCK_DGRAM).sendto(_intstr(Message), (UDP_IP, UDP_PORT)) except: pass socket.close() UPDSend = UPDThreading() UPDSend.Data.put(Message) Edited August 9, 2017 by ShuraBB 1 @ Quote Link to comment Short link Share on other sites More sharing options...
Serfer_78 Posted August 9, 2017 Share Posted August 9, 2017 (edited) Любая переменная есть ссылка. hookedOnGeometryMapped = game.onGeometryMappedЭто сохранение в локальную переменную ссылки на оригинальную функцию. game.onGeometryMapped = hookOnGeometryMappedЭто сохранение в оригинальное место ссылки на твою функцию, хук.Внутри хука ты вызываешь сохраненный оригинал. Схема без хука - вызывающий код получает ссылку на функцию-оригинал из game.onGeometryMapped и вызывает ее. Схема с хуком - вызывающий код получает ссылку на функцию-хук из game.onGeometryMapped и вызывает ее. Внутри функции-хука выполняется оригинал и еще немного кода. Важно!!! Не забываем, что функция часто возвращает какое-то значение. Поэтому нужно его получить (сохранить) при вызове оригинала и вернуть из хука!!! Иначе оригинальный код будет работать некорректно. Т.е. def hookOnGeometryMapped(spaceID, path): result = hookedOnGeometryMapped(spaceID, path) print 'mapName: %s, mapPath: %s' % (path.split('/')[-1], path) return resultВ случае, если функция ничего не возвращает, считается, что она возвращает None. Если ты выполнишь "проброс возврата" для такой функции - ничего плохого не случится. А вот если забудешь, там где он необходим (где функция возвращает не None), получишь некоторое количество лишних проблем. Поэтому рекомендую всегда пробрасывать возврат вне зависимости от того, что возвращает функция. GPCracker это наилучшее описание работы хука! Премного тебе благодарен. Вот теперь все встало в голове на свои места, я понял таки как хукать функции, и даже про подводный камень предупредил ""что функция часто возвращает какое-то значение"" не сомневаюсь что я бы на него нарвался однажды :) >Тут бы по идее потоки запилить но пока не созрел как правильно это реализовать. import threading #импортируем библиотеку для работы с потоками from Queue import Queue # из чего то импортируем что то страшное :) догадываюсь что это работает с очередью сообщений.. class UPDThreading(object): # Объявляем наш класс ,мой кошмар наяву:) пока всячески их пытаюсь избегать))) def __init__(self): # интуиция подсказывает что идет инициализация переменных self.Data = Queue() self.thread = threading.Thread(target = self.SendData) self.thread.setDaemon(True) self.thread.setName('Send UPD Data') self.thread.start() def SendData(self): # объявили функцию while True: # запускаем цикл который работает пока True т.е до первой ошибки Message = self.Data.get() # тут отправка сообщения try: socket.socket(socket.AF_INET, socket.SOCK_DGRAM).sendto(_intstr(Message), (UDP_IP, UDP_PORT)) #ну тут все понятно создается сокет- отправляем меседж))) except: #если ошибка pass # ничего не делаем socket.close() # по окончании закрываем сокет UPDSend = UPDThreading() UPDSend.Data.put(Message) ShuraBB вот это да... Не ожидал однако))) Был бы рядом проставился бы ;-) Вот только я настолько зелен в питоне, что его классы меня слегка пугают, я с отступами то воевал долго)) Тем не менее постараюсь разобраться как все это дело работает! Что то мне подсказывает , что если приаттачить все это дело к коду то возможно код станет гораздо стабильнее, а возможно и быстрее. Получается при хуке оригинальная функция: def onGeometryMapped(spaceID, path): SoundGroups.g_instance.unloadAll() LOG_NOTE('[SPACE] Loading space: ' + path) SoundGroups.g_instance.preloadSoundGroups(path.split('/')[-1]) Принимает по сути вот такой вид)) def onGeometryMapped(spaceID, path): SoundGroups.g_instance.unloadAll() LOG_NOTE('[SPACE] Loading space: ' + path) SoundGroups.g_instance.preloadSoundGroups(path.split('/')[-1]) #отработал основной код функции print 'mapName: %s, mapPath: %s' % (path.split('/')[-1], path) #выполняем наш код в этой функции return result #(А по завершении выполнения хукнутой функции возвращаем в оригинальный код то что должна была вернуть реальная не хукнутая функция.) А если она ничего не возвращала то просто вернется None . Как я понял из приведенного примера , Хук это способ выполнения своего кода в теле оригинальной функции без изменения оригинального кода картошки (или других программ на python) А ведь хук удобен тем, что не нужно расписывать условия при которых выполнится код хука, ибо выполнится он как раз в нужный момент, если правильную функцию хукнуть ! :) А есть ли раздница между таким способом import game def hookOnGeometryMapped(spaceID, path): hookedOnGeometryMapped(spaceID, path) print 'mapName: %s, mapPath: %s' % (path.split('/')[-1], path) hookedOnGeometryMapped = game.onGeometryMapped game.onGeometryMapped = hookOnGeometryMapped И вот таким ? import game hookedOnGeometryMapped = game.onGeometryMapped def hookOnGeometryMapped(spaceID, path): hookedOnGeometryMapped(spaceID, path) print 'mapName: %s, mapPath: %s' % (path.split('/')[-1], path) game.onGeometryMapped = hookOnGeometryMapped Edited August 9, 2017 by Serfer_78 @ Quote Link to comment Short link Share on other sites More sharing options...
ShuraBB Posted August 9, 2017 Share Posted August 9, 2017 >что его классы меня слегка пугают Они не страшные. Да и в твоем случае можно сделать и без классов, просто готовый пример под рукой такой был ;-) >Тем не менее постараюсь разобраться как все это дело работает Вот тебе дока по потокам не плохая А вообще как уже не раз писали - главное уметь спросить Гугл ;-) Python. Лекция 11 - Многопоточные вычисления.pdf 1 @ Quote Link to comment Short link Share on other sites More sharing options...
Serfer_78 Posted August 9, 2017 Share Posted August 9, 2017 (edited) >что его классы меня слегка пугают Они не страшные. Да и в твоем случае можно сделать и без классов, просто готовый пример под рукой такой был ;-) >Тем не менее постараюсь разобраться как все это дело работает Вот тебе дока по потокам не плохая А вообще как уже не раз писали - главное уметь спросить Гугл ;-) Сейчас ознакомлюсь. !!! Прямо мысли прочитал, сижу я значит пишу вопрос на тему "в какой последовательности интерпритатор выполняет команды в питоне))))" вижу твое сообщение читаю .. открываю файл и!!! "В любой момент времени интерпретатор Python знает, какую команду исполнить следующей. После исполнения команды становится известно, какой команде передать управление. Эта ниточка непрерывна в ходе выполнения программы и обрывается только по ее завершении." Бывает же так ... Значит правильно Queue это очередь для потоков на выполнение своей части кода. И вообще в этом документе куча интересного, причем очень коротко и... самое главное на русском! оффтоп: Зря я учил немецкий он мне не пригодился, хотел английский выучить но т.к родители учили немецкий мне было не двузначно намекнуто - выберешь инглиш помощи не будет в его изучении :-( Edited August 9, 2017 by Serfer_78 @ Quote Link to comment Short link Share on other sites More sharing options...
GPCracker Posted August 9, 2017 Share Posted August 9, 2017 Как я понял из приведенного примера , Хук это способ выполнения своего кода в теле оригинальной функции без изменения оригинального кода картошки (или других программ на python)Способ выполнения кода совместно с оригинальной функцией, причем либо до нее, либо после (но никак не посередине), есть возможность вызывать оригинал условно/не выполнять вообще (этого не стоит делать, если нет четкого представления, как функция может использоваться другими мододелами, и что пропуск вызова оригинала повлечет за собой), а также возможность менять значение возврата. Нельзя при помощи хука внедрить код в середину кода оригинальной функции (только добавить свой код в начало или в конец), нельзя выкинуть/добавить строки в оригинальной функции. Это можно сделать только оверрайдом - полным переписыванием функции. Опять же, крайне не советую этого делать, стоит искать более аккуратные варианты, ибо оверрайд часто тянет за собой конфликты с другими модами, и сильно временами нерфит стабильность мода в плане устойчивости к обновлениям картошки. А есть ли раздница между таким способомА если очень хорошо подумать? (Подсказка - никакой). 1 @ Quote Link to comment Short link Share on other sites More sharing options...
Serfer_78 Posted August 9, 2017 Share Posted August 9, 2017 Способ выполнения кода совместно с оригинальной функцией, причем либо до нее, либо после (но никак не посередине), есть возможность вызывать оригинал условно/не выполнять вообще (этого не стоит делать, если нет четкого представления, как функция может использоваться другими мододелами, и что пропуск вызова оригинала повлечет за собой), а также возможность менять значение возврата. Нельзя при помощи хука внедрить код в середину кода оригинальной функции (только добавить свой код в начало или в конец), нельзя выкинуть/добавить строки в оригинальной функции. Это можно сделать только оверрайдом - полным переписыванием функции. Опять же, крайне не советую этого делать, стоит искать более аккуратные варианты, ибо оверрайд часто тянет за собой конфликты с другими модами, и сильно временами нерфит стабильность мода в плане устойчивости к обновлениям картошки. А если очень хорошо подумать? (Подсказка - никакой). Совершенно верно, разницы никакой не заметил, проверил на несколькох разных хуках только что.. @ Quote Link to comment Short link Share on other sites More sharing options...
ShuraBB Posted August 9, 2017 Share Posted August 9, 2017 >Значит правильно Queue это очередь для потоков на выполнение своей части кода. Ты про self.Data = Queue() ? Нет, это стек. .put(...) заносит туда данные а .get() читает из стека 1 @ Quote Link to comment Short link Share on other sites More sharing options...
Serfer_78 Posted August 9, 2017 Share Posted August 9, 2017 (edited) >Значит правильно Queue это очередь для потоков на выполнение своей части кода. Ты про self.Data = Queue() ? Нет, это стек. .put(...) заносит туда данные а .get() читает из стека Не , я про " from Queue import Queue" Хотя про "self.Data = Queue()" тоже полезно было узнать. Edited August 9, 2017 by Serfer_78 @ Quote Link to comment Short link Share on other sites More sharing options...
Serfer_78 Posted August 10, 2017 Share Posted August 10, 2017 (edited) Вот же не задача, разобрался с хуками но теперь с аргументами путаница, пытаюсь получить скорость собственного танка: import BigWorld, Math from Avatar import PlayerAvatar def speedTank(): speed, rspeed = BigWorld.player().getOwnVehicleSpeeds() return '%s %d %d' % ('speed:', speed, rspeed) не могу разобраться что передать в функцию ... def speedTank(speed, rspeed): #или def speedTank(self, getInstantaneous=False): #а возможно def speedTank(self, speed, rspeed): Самое комичное то что вчера написал функцию, она работала, передавала положительную скорость (например (10) и отрицательную (-10)) , при сохранении перезаписал документ и удалил функцию, а теперь не помню что я там накалякал)) возможно что то типа def speedTank(self): speed, rspeed = BigWorld.player().getSpeed() return '%s %d %d' % ('speed:', speed, rspeed) Не пойму где моя ошибка, в логах питона чисто . Edited August 10, 2017 by Serfer_78 @ Quote Link to comment Short link Share on other sites More sharing options...
Serfer_78 Posted August 12, 2017 Share Posted August 12, 2017 (edited) Кучу примеров кода модов для танков можно на гитхабе найти. например у меня в репо https://github.com/spoter Доброго времени суток , нашел в твоем моде AdvancedAimingSystem функцию : def getSpeed(self): vehicle = self.getVehicle() return abs(vehicle.filter.speedInfo.value[0]) if vehicle is not None else None на ее базе попытался вывести в сообщении скорость собственного танка но результат 0, если не затруднит подскажи пожалуйста как правильно ей можно воспользоваться, может есть какие то аналоги ? def getSpeed(self): vehicle = BigWorld.entity(self.playerVehicleID) speed = abs(vehicle.speedInfo.value[0]) if vehicle is not None else None return '%s %d' % ('Speed', speed) Edited August 12, 2017 by Serfer_78 @ Quote Link to comment Short link Share on other sites More sharing options...
MakcT40 Posted August 13, 2017 Share Posted August 13, 2017 (edited) скорость собственного танка См. в Avatar.py функцию getOwnVehicleSpeeds (и, на всякий случай, __dumpVehicleState). Edited August 13, 2017 by MakcT40 1 @ Quote Link to comment Short link Share on other sites More sharing options...
Serfer_78 Posted August 14, 2017 Share Posted August 14, 2017 (edited) См. в Avatar.py функцию getOwnVehicleSpeeds (и, на всякий случай, __dumpVehicleState). Я уже ее бедную замучал)) from Avatar import PlayerAvatar def speedTank(): speed, rspeed = BigWorld.player().getOwnVehicleSpeeds() return '%s %d %d' % ('speed:', speed, rspeed) И аргументы ей разные совал, результат не отдает, весь мозг вывихнул и не пойму что ей надо. В __dumpVehicleState имеется полностью вся инфа.. Однажды запустил лончер дочерним процессом и в лог из этой функции получил вот такую картину.. 2017-07-29 03:06:55.078: NOTICE: [NOTE] (scripts/client/game.py, 464): [sPACE] Loading space: spaces/19_monastery2017-07-29 03:11:12.353: NOTICE: [NOTE] (scripts/client/Avatar.py, 3537): Arena type: ('19_monastery',) 2017-07-29 03:11:12.353: NOTICE: [NOTE] (scripts/client/Avatar.py, 3538): Vehicle position: ((45.6436, 5.31994, 420.044),) 2017-07-29 03:11:12.353: NOTICE: [NOTE] (scripts/client/Avatar.py, 3539): Vehicle direction (y, p, r): ((-3.0541555881500244, -0.02854049578309059, 0.02158796228468418),) 2017-07-29 03:11:12.354: NOTICE: [NOTE] (scripts/client/Avatar.py, 3540): Vehicle speeds: ((-3.9845138299909877e-10, -1.2582367370228553e-09),) 2017-07-29 03:11:12.354: NOTICE: [NOTE] (scripts/client/Avatar.py, 3542): Vehicle type: ('germany:G23_Grille',) 2017-07-29 03:11:12.354: NOTICE: [NOTE] (scripts/client/Avatar.py, 3543): Vehicle turret: ('Grille_mod_1',) 2017-07-29 03:11:12.354: NOTICE: [NOTE] (scripts/client/Avatar.py, 3544): Vehicle gun: ('_150mm_sFH13_L17',) 2017-07-29 03:11:12.354: NOTICE: [NOTE] (scripts/client/Avatar.py, 3545): Shot point: ((49.1623, 12.5297, -52.905),) Но и __dumpVehicleState не чего не отдает.. Но тем не менее спасибо что откликнулись... Как видим из лога , название карты отдает game.py , а остальные данные уже идут из аватара. Как уже выше писал , у меня получалось выдернуть скорость и обновлять ее "realtime" но я по неосторожности удалил готовую функцию)) Ребята кто шарит подскажите с аргументами, какие указать чтобы получить результат? def speedTank(???, ???): Edited August 14, 2017 by Serfer_78 @ Quote Link to comment Short link Share on other sites More sharing options...
Olegansv Posted August 15, 2017 Share Posted August 15, 2017 def speedTank(???, ???): from gui.Scaleform.daapi.view.meta.DamagePanelMeta import DamagePanelMeta __speed__ = None old_as_updateSpeedS = DamagePanelMeta.as_updateSpeedS def new_as_updateSpeedS(self, speed): global __speed__ __speed__ = speed return old_as_updateSpeedS(self, speed) DamagePanelMeta.as_updateSpeedS = new_as_updateSpeedS def speedTank(): return __speed__ 1 @ Quote Link to comment Short link Share on other sites More sharing options...
Serfer_78 Posted August 16, 2017 Share Posted August 16, 2017 DesiredShotPoint - это для системы прицеливания, куда пушка наводится. ShotPoint - это передается на сервер для отрисовки камеры наблюдателя. Карта может иметь любую расстановку баз. К координатной системе они точно не привязаны. Если они тебе сильно нужны, их координаты можно получить из данных арены. Матрица танка есть матрица преобразования из локальной координатной системы танка в глобальную спейса (карты). Читай документацию к BigWorld. Уже неоднократно постил, поищи на форуме по аттачам. День добрый! То есть все что начинается с get передается на сервер? Я правильно понял? @ Quote Link to comment Short link Share on other sites More sharing options...
GPCracker Posted August 17, 2017 Share Posted August 17, 2017 То есть все что начинается с get передается на сервер? Я правильно понял?Нет. Читай документацию к BigWorld, если тебе это интересно. Почитай также про RPC в инете, base и cell модули в BigWorld. Но не думаю, что для твоих задач это реально нужно. 1 @ Quote Link to comment Short link Share on other sites More sharing options...
Serfer_78 Posted August 25, 2017 Share Posted August 25, 2017 (edited) >Тут бы по идее потоки запилить но пока не созрел как правильно это реализовать. import threading from Queue import Queue class UPDThreading(object): def __init__(self): self.Data = Queue() self.thread = threading.Thread(target = self.SendData) self.thread.setDaemon(True) self.thread.setName('Send UPD Data') self.thread.start() def SendData(self): while True: Message = self.Data.get() try: socket.socket(socket.AF_INET, socket.SOCK_DGRAM).sendto(_intstr(Message), (UDP_IP, UDP_PORT)) except: pass socket.close() UPDSend = UPDThreading() UPDSend.Data.put(Message) Вообщем начитавшись литературы слепил простенький код для запуска UDP в отдельном потоке... def threadDecorate(object): def decorate(*args, **kwargs): th = threading.Thread(target=object, args=args, kwargs=kwargs) th.setDaemon = True th.start() return decorate @threadDecorate def sendMessage(Message): try: socket.socket(socket.AF_INET, socket.SOCK_DGRAM).sendto(Message, (UDP_IP, UDP_PORT)) socket.close() except: pass Работает как часики, но за пример благодарен. Т.к подтолкнул в нужное русло... Edited August 25, 2017 by Serfer_78 @ Quote Link to comment Short link Share on other sites More sharing options...
GPCracker Posted September 21, 2017 Share Posted September 21, 2017 (edited) On 25.08.2017 at 10:11 PM, Serfer_78 said: Вообщем начитавшись литературы слепил простенький код для запуска UDP в отдельном потоке... Почитай про модуль adisp. Edited September 21, 2017 by GPCracker @ Quote Link to comment Short link Share on other sites More sharing options...
Serfer_78 Posted September 22, 2017 Share Posted September 22, 2017 (edited) 22 часа назад, GPCracker сказал: Почитай про модуль adisp. Этот модуль в Bigworld или в Pythin ? Что то мало про него на форуме, а может не нашел... Edited September 22, 2017 by Serfer_78 @ Quote Link to comment Short link Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.