Показать сообщение отдельно
Старый 07.04.2015, 16:07   #62
Алексанw24
Нуб
Аватар для Алексанw24
OFFLINE
Регистрация: 01.04.2015
Сообщений: 0
Благодарностей:
0 всего
Репутация: 1

Начнём по порядку.
1)Класс с подключением библиотек win32
Код:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;


namespace Win32Lib
{
    public static class Win32
    {

        public const int WM_SETCURSOR = 0x020;
        public const int WM_COMMAND = 0x111;
        public const int WM_KEYDOWN = 0x100;
        public const int WM_KEYUP = 0x101;
        public const int WM_CHAR = 0x102;
        public const int WM_MOUSEMOVE = 0x200;
        public const int WM_LBUTTONDOWN = 0x201;
        public const int WM_LBUTTONUP = 0x202;
        public const int WM_LBUTTONDBLCLK = 0x203;

        public const int GWL_EXSTYLE = -20;
        public const int WS_EX_TOOLWINDOW = 0x00000080;
        public const int WS_EX_APPWINDOW = 0x00040000;

        public delegate bool EnumThreadDelegate(IntPtr hWnd, IntPtr lParam);

        [DllImport("User32.dll")]
        public static extern IntPtr FindWindow(string strClassName, string strWindowName);


        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern IntPtr FindWindowEx(int parentHandle, IntPtr childAfter, string lclassName, string windowTitle); 


        [DllImport("user32.dll")]
        public static extern bool PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);


        [DllImport("User32.dll")]
        public static extern Int32 SendMessage(IntPtr hWnd, uint Msg, int wParam, Int64 lParam);


        [DllImport("user32.dll")]
        public static extern int SetWindowLong(IntPtr window, int index, int
        value);


        [DllImport("user32.dll")]
        public static extern int GetWindowLong(IntPtr window, int index);

        [DllImport("user32.dll")]
        public static extern byte VkKeyScan(char ch);

        [DllImport("user32.dll", SetLastError = true)]
        public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

        [DllImport("user32.dll")]
        public static extern bool ShowWindow(IntPtr hwnd, int nCmdShow);



        [DllImport("kernel32.dll")]
        public static extern int OpenProcess(ProcessAccessFlags dwDesiredAccess, bool bInheritHandle, int dwProcessId);

        [DllImport("kernel32.dll")]
        public static extern bool WriteProcessMemory(int hProcess, uint lpBaseAddress, byte[] buffer, int size, int lpNumberOfBytesWritten);

        [DllImport("kernel32.dll")]
        public static extern bool ReadProcessMemory(int hProcess, uint lpBaseAddress, byte[] buffer, int size, int lpNumberOfBytesRead);

        [DllImport("kernel32.dll")]
        public static extern Int32 CloseHandle(int hProcess);

        [DllImport("user32.dll")]
        public static extern bool EnumThreadWindows(int dwThreadId, EnumThreadDelegate lpfn, IntPtr lParam);

        public enum ProcessAccessFlags : uint
        {
            All = 0x001F0FFF,
            Terminate = 0x00000001,
            CreateThread = 0x00000002,
            VMOperation = 0x00000008,
            VMRead = 0x00000010,
            VMWrite = 0x00000020,
            DupHandle = 0x00000040,
            SetInformation = 0x00000200,
            QueryInformation = 0x00000400,
            Synchronize = 0x00100000
        }
    }

    public static class ShowMode
    {
        public const int SW_FORCEMINIMIZE = 11;
        public const int SW_HIDE = 0;
        public const int SW_MAXIMIZE = 3;
        public const int SW_MINIMIZE = 6;
        public const int SW_RESTORE = 9;
        public const int SW_SHOW = 5;
        public const int SW_SHOWDEFAULT = 10;
        public const int SW_SHOWMAXIMIZED = 3;
        public const int SW_SHOWMINIMIZED = 2;
        public const int SW_SHOWMINNOACTIVE = 7;
        public const int SW_SHOWNA = 8;
        public const int SW_SHOWNOACTIVATE = 4;
        public const int SW_SHOWNORMAL = 1;
    }
}
2.Класс, который я использую для чтения из памяти
Код:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Win32Lib;
using System.ComponentModel;

namespace MyMagic
{
    class WhiteMagic
    {

        int handler;

        public WhiteMagic(int processId)
        {
            handler = Win32.OpenProcess(Win32.ProcessAccessFlags.All, false, processId);
        }


        public uint GetAddressByOffsets(uint[] offsets)
        {
            uint ret=offsets[0];

            for(int i=1;i<offsets.Length;i++)
            {
                ret = ReadUint(ret);
                ret += offsets[i];
            }
            return ret;
        }

        public uint ReadUint(uint offset)
        {
            
            byte[] buff = new byte[4];
            Win32.ReadProcessMemory(handler, offset, buff, 4, 0);
            uint ret=BitConverter.ToUInt32(buff, 0);
            return ret;
        }

        public void Close()
        {
            Win32.CloseHandle(handler);
        }
    }
}
P.S.Пробовал открывать с правами только на чтение - не помогает.
Функция GetAddressByOffsets использую для высчитывания адресов флагов и параметров при старте бота один раз.
3.Пример обращения (привожу не весь код - там 500 с лишним строк - только то что выполняется в таймерах)
Код:
private void checkOffsets(object sender, ElapsedEventArgs e)
        {
            if(gather_existance.Interval>1000)
            {
                gather_existance.Interval = rnd.Next(80, 120);
            }
            if(tera!=null && checkGatherFlag() && currentState==gatherStates.LOOKING_FOR_RESOURCE)
            {
                setStatus(gatherStates.WAITING_FOR_GATHER);
                log_form.logText("Ресурс найден");
                //this.Invoke((MethodInvoker)delegate() { log.AppendText("Find ore/plant" + Environment.NewLine); });
                gather_existance.Enabled = false;
                if (tera.ReadUint(ClientAddresses.IS_GATHERING) == 0)
                {
                    send_one();
                }
               
                check_start_gather.Interval = rnd.Next(30,70);
                check_start_gather.Elapsed += checkStartGather;
                check_start_gather.Enabled = true;
            }
        }

        private Boolean checkGatherFlag()
        {
            //Проверка флага наличия в таргете руды. Оффсетов было много и с разными значениями. Для этого при 0 - нет в таргете руды, при 1 - руда трава и т.п.

            if (tera!=null && tera.ReadUint(ClientAddresses.TARGET_GATHER_FLAG) == 1)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private void checkFinishGather(object sender, ElapsedEventArgs e)
        {
            Win32.ShowWindow(handler, ShowMode.SW_SHOWNOACTIVATE);
            if (tera != null && tera.ReadUint(ClientAddresses.IS_GATHERING) == 0 && currentState==gatherStates.GATHERING)
            {
                log_form.logText("Сбор завершён");
                //this.Invoke((MethodInvoker)delegate() { log.AppendText("Finish gathering" + Environment.NewLine); });
                finish_gathering.Enabled = false;
                gather_existance.Enabled = true;
                check_start_gather.Enabled = false;

                setStatus(gatherStates.LOOKING_FOR_RESOURCE);

                uint wp = tera.ReadUint(ClientAddresses.WORK_POINTS);
                redrawProgressBar((int) wp);
                if (wp < 10 && stopZeroWork.Checked)
                {
                    this.Invoke((MethodInvoker)delegate() { 
                        button1_Click(null, null); 
                    });
                    log_form.logText("Закончились очки работы");
                }

            }
        }

        private void checkStartGather(object sender, ElapsedEventArgs e)
        {
            if (tera != null && tera.ReadUint(ClientAddresses.IS_GATHERING) == 0 && tera.ReadUint(ClientAddresses.TARGET_GATHER_FLAG) == 1  && currentState == gatherStates.WAITING_FOR_GATHER)
            {
                send_one();
                
            }
            else if(tera!=null && tera.ReadUint(ClientAddresses.TARGET_GATHER_FLAG)==0 && currentState==gatherStates.WAITING_FOR_GATHER)
            {
                TimeSpan delta = DateTime.Now - last_change_status;
                if (delta.TotalMilliseconds > 3000)
                {
                    log_form.logText("Кто-то скрысил ресурс");
                    //this.Invoke((MethodInvoker)delegate() { log.AppendText("Someone start gather (not me)" + Environment.NewLine); });
                }
                else
                {
                    gather_existance.Interval = 20000;
                    //log_form.logText("tst");
                    //this.Invoke((MethodInvoker)delegate() { log.Lines = log.Lines.Reverse().Skip(2).Reverse().ToArray(); log.AppendText(Environment.NewLine); });
                }
                
                check_start_gather.Enabled = false;
                gather_existance.Enabled = true;
                setStatus(gatherStates.LOOKING_FOR_RESOURCE);
            }
            else if(tera!=null && tera.ReadUint(ClientAddresses.TARGET_GATHER_FLAG)==1 && tera.ReadUint(ClientAddresses.IS_GATHERING) == 1 && currentState==gatherStates.WAITING_FOR_GATHER)
            {
                setStatus(gatherStates.GATHERING);
                log_form.logText("Начат сбор");
                //this.Invoke((MethodInvoker)delegate() { log.AppendText("Start gathering" + Environment.NewLine); });
                check_start_gather.Enabled = false;
                finish_gathering.Interval = rnd.Next(30,70);
                finish_gathering.Elapsed += checkFinishGather;
                finish_gathering.Enabled = true;
            }
        }
Комментарии по этому куску.
checkOffsets - выполняется по таймеру раз в 50-100мс. Проверяет наличие в таргете ресурса. То что для установки использую рандом - вчера тестировал - думал, что возможна какая-то кореляция между таймерами и поэтому всё подвисает.

Как только боту в таргет попадает ресурс он останавливает этот таймер и вызывает таймер проверки начала сбора т.е. я шлю нажатие кнопки сбора до тех пор пока не появится флаг того, что я собираю ресурс.(checkStartGather)

После того как я получил подтверждение старта сбора (флаги сбора и нахождение в таргете ресурса) таймер проверки начала сбора останавливается и запускается таймер проверки окончания сбора.
(Про интервал в 20000 после окончания сбора руда несколько секунд ещё таргете. По этому моменту я выставляю таймер на проверку сбора в 20с(вчера тестил с этой штукой, но бот всё равно зависал так что это не принципиально)

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