Автокликер Clickermann :: Форум
Основной раздел => Предложения => Topic started by: ya12 on January 05, 2019, 02:51:15 PM
-
При попытке оптимизации кода, уперся в ограничение размера блока читаемой информации.
Желательно снять ограничения в READMEM на SIZE, для чтения текстовых данных или добавить новую команду для чтения текстовых данных из памяти процесса.
-
Ну тут можно же извернуться в пару строк. Читать побайтово и писать в массив или в строку.
Вот пример чтения строки из памяти кликермана:
(https://i.imgur.com/yguffhQ.png)
Или имелось в виду чтото другое?
-
А в каком формате у вас текст? Однобайтовый ANSI? Двухбайтовый Юникод?..
Нет там никаких "ограничений". Все что кажется ограничением - это лишь недопонимание того, что и откуда берется.
Команда чтения памяти - команда довольно низкого уровня. Самого представления данных (число, число с точкой, строка) в ней быть не должно.
size в данном случе лишь описание стандартных СИшных целочисленных типов, сделанное по аналогии с Artmoney
-
Символы 2х байтные. Длина текста до 96 байт в конце 0x0.
Читаю данные из массива указателей в памяти процесса. Процесс добавляет новые указатели в конец массива и затирает устаревшие, сдвигая хвост ближе к началу.
Абсолютные адреса объектов в конце массива изменяются, если одновременно удаляются и добавляются новые объекты (дроп, смерть мобов, уход и появление в зоне видимости).
Нужно найти по координатам ближайшего моба. На 35-50 указателей уходит 2-3 сек. А могут быть сотни, если дроп не собирать - тысячи объектов. Пока досчитаешь до конца, в середине что-нибудь изменится.
Сначала идут фильтры. Отбор всех мобов, отбор живых мобов (мертвые исчезают не сразу), исключение мобов на других уровнях(выше-ниже), посимвольное чтение имени моба, отбор нужных имен мобов (в этом же цикле определяется ближайший).
Первые 12 объектов, вещи на игроке, последний объект сам игрок. Остальное мобы, персы, npc, дроп.
$minD = 0
print("+ТАБЛИЦА МОБОВ+")
FOR ($a=12, $a < $_kp) //0
$_addr_zap1 = 0x0000000C * $a + $_tab + 8
$_zap1 = readmem($_pid, $_addr_zap1, 4)
if($_zap1 != 0x00000000)
$_addr_UserTO = $_zap1 + 0x00000004 //адрес таблицы User в ТО
$_UserTO = readmem($_pid, $_addr_UserTO, 4)
if($_UserTO != 0x00000000)
//перс 00000, моб 00101, npc 00100
$_UserTO_0 = readmem($_pid, ($_UserTO + 0x00000000), 4)
if($_UserTO_0 = 0)
$_UserTO_4 = readmem($_pid, ($_UserTO + 0x00000004), 4)
if($_UserTO_4 = 0)
$_UserTO_8 = readmem($_pid, ($_UserTO + 0x00000008), 4)
if($_UserTO_8 = 1)
$_UserTO_C = readmem($_pid, ($_UserTO + 0x0000000C), 4)
if($_UserTO_C = 0)
$_UserTO_10 = readmem($_pid, ($_UserTO + 0x00000010), 4)
if($_UserTO_10 = 1)
$_mobHPmax = readmem($_pid, ($_UserTO + 0x78), 4) // mobHPmax
$_mobHPtek = readmem($_pid, ($_UserTO + 0x7c), 4) // mobHPtek
if(($_mobHPtek = 0)and($_mobHPmax!=0)) //моб мертв
else //моб жив или нет данных
//начало таблицы AActor в ТО
$_AActorTO = readmem($_pid, ($_UserTO + 0x00000158), 4)
if($_AActorTO != 0x00000000)
$_koor_Z1 = readmem($_pid, ($_AActorTO + 0x000001C4), 2)
$_koor_Z0 = readmem($_pid, ($_AActorTO + 0x000001C6), 2)
CALL("float_int.dll", $_koor_Z0, $_koor_Z1)
$_koor_Zf = $_return1
$_mod = $_koor_Zf - $_koor_Zpf
if(($_mod < $_modZ) and ($_mod > $_mod_Z)) //искл по высоте Z
//начало таблицы SrvAActor в ТО
$_SrvAActorTO = readmem($_pid, ($_AActorTO + 0x0000003c), 4)
if($_SrvAActorTO != 0x00000000)
$_AActorTrgTO = readmem($_pid, ($_SrvAActorTO + 0x00000400), 4)
if($_AActorTrgTO != 0x00000000)
$_IDtrgTO = readmem($_pid, ($_AActorTrgTO + 0x00000060), 4) //ID цели из ТО
IF($_IDtrgTO = $_ID)
print("В ФОКУСЕ")
//тут будет досрочный выход из цикла, а пока заглушка
end_if
end_if
end_if
//побайтно счититываем имя
$_name = ""
$_kb = readmem($_pid, ($_UserTO + 0x0000001C),2) //<----
$b = 0
WHILE ($_kb != 0)
if($_kb!=39)
$_bukva = char($_kb)
$_name = strconcat ($_name, $_bukva)
end_if
$b = $b + 2
$_kb = readmem($_pid, ($_UserTO + 0x0000001C + $b), 2)
end_cyc
for($r=0, $r < $_kol_name) //дано несколько имен
if($arr_name[$r] = $_name) //проверка на совпадение
$_n = $_n + 1
$_koor_X1 = readmem($_pid, ($_AActorTO + 0x000001BC), 2)
$_koor_X0 = readmem($_pid, ($_AActorTO + 0x000001BE), 2)
CALL("float_int.dll", $_koor_X0, $_koor_X1)
$_koor_Xf = $_return1
$_koor_Y1 = readmem($_pid, ($_AActorTO + 0x000001C0), 2)
$_koor_Y0 = readmem($_pid, ($_AActorTO + 0x000001C2), 2)
CALL("float_int.dll", $_koor_Y0, $_koor_Y1)
$_koor_Yf = $_return1
$_ar_d[$_n] = INT(DIST($_koor_Xpf,$_koor_Ypf,$_koor_Xf,$_koor_Yf))
$_ar_UserTO[$_n] = $_UserTO //начало UserTO
$_ar_AActorTO[$_n] = $_AActorTO //начало AActorTO
$_ar_name[$_n] = $_name
$_ar_id[$_n] = readmem($_pid, ($_UserTO + 0x00000018), 4) //id
//определение min1
if(($_n = 0) or ($_ar_d[$_n] < $min1D))
$min1D = $_ar_d[$_n]
$min1In = $_n
end_if
$r = $_kol_name //досрочный выход если имя совпало
end_if
end_cyc
end_if
end_if
end_if
end_if
end_if
end_if
end_if
end_if
end_if
end_if
$_kp = readmem($_pid, $_addr_iTO, 4) - 1 //кол-во - игрок
END_CYC
print("-ТАБЛИЦА МОБОВ-")
Для ускорения хотел там, где в памяти текст, читать сразу 96 байт, а не по 2 байта выбирать.
-
Нужно найти по координатам ближайшего моба. На 35-50 указателей уходит 2-3 сек. А могут быть сотни, если дроп не собирать - тысячи объектов. Пока досчитаешь до конца, в середине что-нибудь изменится.
Может ты и прав, еслиб читало сразу пачкой, это бы ускорило работу. Но мое мнение, все это время уходит на другие действия, типа чтения указателей и прочего.
Вот к примеру я попробовал только читать 50 раз по 96 байт (возможно имелось ввиду не байт а символов?) и составлять строку.
300-400мс, тоже не мало, согласен, но все же...
$pid = HGETPID($_hwnd_self)
$adr = 0x00B978BE
$t = $_ms
FOR($n=0,$n<50) //50 раз по 96 байт
$str = ""
FOR($a=$adr,$a < $adr+96,2)
$str = STRCONCAT ($str, char(READMEM($pid, $a, 2)))
END_CYC
// print($str)
END_CYC
print($_ms - $t) // 300-400мс
halt
Еще, не по теме :-X
Вижу вызываешь длл для перевода из целого в число с точкой "float_int.dll" . А тебе не кажется, что кликер посчитает "немного" быстрее чем вызов отдельного файла, ожидание ответа и прием параметра? http://crapware.aidf.org/forum/index.php?topic=3749.msg29132#msg29132 А еще если имен $_kol_name будет целая куча?
$float = POW(-1,int($int/2147483648)) * pow(2,int($int/8388608) - int($int/2147483648)*256-127) * (1+(($int - (int($int/8388608) - int($int/2147483648)*256)*8388608 - int($int/2147483648)*2147483648)/POW(2,23)))
Можно оптимизировать, разделить на отдельные переменные чтобы не считать лишнее, будет еще быстрее.
Но я уверен, ты видел эти расчеты, значит вызов длл всеже быстрее? :-\
-
48 символов максимально длинное название. Каждый символ 2 байта.
Время тратится на перевод чисел с плавающей точкой в целое. Вычисление расстояния между ними. Чтение и сравнение имен.
1 Для ускорения сделаю 2 списка имен. Нужных и не нужных мобов. Который короче, тот и пойдет в работу.
2 Попробую распараллелить чтение и обработку массива на несколько потоков.
3 Твоя формула на 1мс считает быстрее DLL (для передачи в DLL приходиться разбивать 4 байта на 2х2 байта, а внутри DLL собирать обратно).
-
2 Попробую распараллелить чтение и обработку массива на несколько потоков.
обратно).
Скорости потоки не добавляют, проверено. Все действия и вычисления между потоками выполняются по очереди, не одновременно. Как вариант - распараллелить чтение и обработку массива на несколько кликерманов.
3 Твоя формула на 1мс считает быстрее DLL (для передачи в DLL приходиться разбивать 4 байта на 2х2 байта, а внутри DLL собирать обратно).
Я проверил, моя формула работает медленнее чем вызов длл :o :-\ . НО это ничтожные 0.2 мс формулой, и 0.15 мс вызовом длл ;D. Проверял на прогонах по 1000 переводов из int во float.
И всеже формулой в твоем варианте выйдет быстрее, так как не нужно два раза читать память по 2 байта, а за один раз прочитать 4 и сразу пересчитать в нужное с точкой.
Кстати c "float_int.dll" пришлось повозиться, так как он не принимал большие числа. Только со временем понял что на выходе то может выйти настолько большое число, которое просто не влезет в возвращаемую $_return1 (4 байта) :D.
Еще варианты:
Сохранить в файл дамп нужного куска памяти, и далее работать с этим файлом - КМ v4.14 - FREADDATA. Неуверен, что так будет быстрее :D
Стопроцентный вариант, не в обиду кликерману :-X : переписать все эти чтения памяти и вычисления полностью в длл. Вроде там ничего сложного нет, почти копипаст. Время выполнения уменьшится до пары миллисекунд ;).
-
Если бы Johnny тип передаваемых данных поднял до int64, а на вход и выход массивы. Тогда можно все в DLL считать. А в нынешнем варианте, вход переменные через запятую, выход 4 байта и все.
-
Если бы Johnny тип передаваемых данных поднял до int64, а на вход и выход массивы. Тогда можно все в DLL считать. А в нынешнем варианте, вход переменные через запятую, выход 4 байта и все.
Вообще, int64 и кликер не поддерживает :(. Скорее всего при больших числах в нем идет тип float 4 байтный (мне так кажется...).
Покажу на примере:
$b = 72000000000000000 //возьмем какоето число, больше 32 бит.
FOR($a=0,$a<100)
print($b + $a)
wait(1)
END_CYC
halt
лог:
15:57:02 72000000000000000
15:57:03 72000000000000000
15:57:04 72000000000000000
15:57:05 72000000000000000
15:57:06 72000000000000000
15:57:07 72000000000000008
15:57:08 72000000000000008
15:57:09 72000000000000008
15:57:10 72000000000000008
15:57:11 72000000000000008
15:57:12 72000000000000008
15:57:13 72000000000000008
15:57:14 72000000000000016
15:57:15 72000000000000016
15:57:16 72000000000000016
15:57:17 72000000000000016
15:57:18 72000000000000016
15:57:19 72000000000000016
Поэтому с передачей туда сюда int64 пока можно подождать. А вот массивы передавать, это тема, поддерживаю ;).
Но пока нет такой возможности, можно воспользоваться передачей инфы через файл - ини или тхт, не важно. Работает безотказно и быстро.
-
Сейчас в CALL используется тип Integer 4 байта, диапазон от -2 147 483 648 до 2 147 483 647
А мне нужен минимум Longword 4 байта, диапазон от 0 до 4 294 967 295
Int64 - 8 байт или Real - 6 байт - это я с запасом мечтал.
Соответственно что бы проходили числа больше 2 147 483 647 или передаем 2x2 байта и в DLL объединяем обратно в 4 байта, или пересчитываем с учетом минуса.
-
Ну так это же уже решалось ранее. Просто переделываем отрицательное число в беззнаковое. И наоборот в отрицательное если оно больше 2147483647
//перевод в беззнаковое число, если оно отрицательное.
IF($int < 0)
$int = $int + 4294967296
END_IF
//И наоборот, если оно больше 2147483647 в отрицательное
IF($int > 2147483647)
$int = $int - 4294967296
END_IF
Както так, вроде не ошибся...
-
В обоих случаях лишние расчеты.
Я прикинул, пожалуй вычисления ближайшего моба можно запихнуть в DLL. На выходе получить указатель на начало таблицы User. А остальные данные читать из Кликермана.